C++重载与多态

 

运算符重载

定义:运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。运算符重载的实质就是函数的重载。

优点:可以改变现有运算符的操作方式,以用于类类型,使得程序看起来更加直观。

·运算符重载的规则

(1)c++中的运算符除了少数几个之外,全部可以重载,而且只能重载c++中已经有的运算符。

(2)重载之后运算符的优先级和结合性都不会变。

(3)运算符重载是针对新类型数据的实际需要,对原有的运算符进行适当改造。一般来讲,重载功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。

注意:有些操作符是不能重载的,它们是类属关系运算符“.”、成员指针运算符“.*”、作用域分辨符“::”和三目运算符"?:"。

 

运算符重载分类:1.重载为类的非静态成员函数。2.重载为非成员函数

语法形式:

返回类型 operator 运算符(形参表)
{
    函数体;
}

  提示:当以非成员函数形式重载运算符时,有时需要访问运算符参数所涉及类的私有成员,这时可以把该函数声明为类的友元函数。

     当运算符重载为类的成员函数时,函数的参数个数比原来的操作数个数要少一个(后置“++”“--”除外)

     当重载为非成员函数时,参数个数与原操作数个数相同

 

·运算符重载为成员函数

对于双目运算符B,如果要重载为类的成员函数,使之能够实现表达式oprd1 B oprd2,其中oprd1为A类的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参类型是oprd1.operator B(oprd2)。

*对于后置运算符如“++”、“--”,如果要将它们重载为类的成员函数,用来实现表达式oprd++或oprd--,其中oprd为A类的对象,那么运算符就应当重载为A类的成员函数,这时函数要带有一个整型(int)形参。这里的int类型参数在运算中不起任何作用,只是用于区别后置++--与前置++--。

例1:复数类加减法运算重载

#include<iostream>
using namespace std;
class Complex                                                      //复数类定义
{                                                                  
public:                                                            //外部接口
	Complex(double r=0.0,double i=0.0):real(r),imag(i){}           //构造函数
	Complex operator+(const Complex &c2)const;                     //运算符+重载成员函数
	Complex operator-(const Complex &c2)const;                     //运算符-重载成员函数
	void display() const;                                          //输出复数
private:                                                           //私有数据成员
	double real;                                                   //复数实部
	double imag;                                                   //复数虚部
};
Complex Complex::operator+(const Complex &c2)const                 //重载运算符函数实现
{
	return Complex(real + c2.real, imag + c2.imag);                //创建一个临时无名对象作为返回值
}
Complex Complex::operator-(const Complex &c2)const
{
	return Complex(real - c2.real, imag - c2.imag);
}
void Complex::display()const
{
	cout << "(" << real << "," << imag << ")" << endl;
}
int main()
{
	Complex c1(5, 4), c2(2, 10), c3;
	cout << "c1="; c1.display();
	cout << "c2="; c2.display();
	c3 = c1 - c2;
	cout << "c3=c1-c2=";
	c3.display();
	c3 = c1 + c2;
	cout << "c3=c1+c2=";
	c3.display();
	system("pause");
	return 0;
}

  运算结果:

 

 本例重载的“+”,“-”函数中,都是创建一个临时的无名对象作为返回值,它的含义是:调用Complex构造函数创建一个临时对象并返回它。也可以如下进行返回:

 

Complex Complex::operator+(const Complex &c2)const
{
    Complex c(real+c2.real,imag+c2.imag);
    return c;
}

 

 

例2:前置++与后置++

#include<iostream>
using namespace std;
class Point
{
public:
	Point(double r = 0.0, double i = 0.0) //:real(r), imag(i) { }
	{
		real = r;
		imag = i;
	}
	Point& operator++();
	Point operator++(int);
	void display() const;

	
private:
	double real;
	double imag;
};
void Point::display() const
{
	cout << real << ' ' << imag << endl;
}

Point & Point::operator++()
{
	real++;
	imag++;
	return *this;
}
Point Point::operator++(int)
{
	Point old = *this;
	++(*this);
	return old;

	
}
int main()
{
	Point point(1, 2);
	(point++).display();
	(++point).display();
	system("pause");
	return 0;
}

  

运行结果如图:

 

 

那么将操作符重载函数同时进行引用会怎么样呢

Point& operator++();
Point operator++(int);

改为

Point& operator++();
Point& operator++(int);

代码运行截图

 

 

但是运行出错,那是因为后置++加了引用符号之后会导致old释放后无法接收,需要另外定义一个对象接收old值来进行输出。

 

完整代码如下

#include<iostream>
using namespace std;
class Point
{
public:
	Point(double r = 0.0, double i = 0.0) //:real(r), imag(i) { }
	{
		real = r;
		imag = i;
	}
	Point& operator++();
	Point& operator++(int);
	void display() const;

	
private:
	double real;
	double imag;
};
void Point::display() const
{
	cout << real << ' ' << imag << endl;
}

Point & Point::operator++()
{
	real++;
	imag++;
	return *this;
}
Point & Point::operator++(int)
{
	Point old = *this;
	++(*this);
	return old;

	
}
int main()
{
	Point point(1, 2),b;
	(++point).display();
	b = point++;
	b.display();
	
	system("pause");
	return 0;
}

 运行结果如图:

 

 

 后置++加了引用符号之后会导致old释放后无法接收,需要另外定义一个对象接收old值来进行输出。

总之:前自增函数加&是方便连续自增,用于返值返回的是引用而不是赋值,可以减少内存,类似于函数传值和传地址。也就是说,该函数返值会通过地址传送的方式给到函数调用者要求的返回值,这样可以节省对象赋值造成的内存浪费,通常用于返值是大型对象(而不是简单变量类型)的时候。

 ·运算符重载为非成员函数

例:重载+-<<

#include<iostream>
using namespace std;
class Complex
{
public:
	Complex(double r = 0.0, double i = 0.0) :real(r), imag(i){}
	friend Complex operator+(const Complex &c1, const Complex &c2);
	friend Complex operator-(const Complex &c1, const Complex &c2);
	friend ostream & operator<<(ostream &out, const Complex &c);
private:
	double real;
	double imag;
};
Complex operator+(const Complex &c1, const Complex &c2)
{
	return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
Complex operator-(const Complex &c1, const Complex &c2)
{
	return (c1.real - c2.real, c1.imag - c2.imag);
}
ostream & operator<<(ostream &out, const Complex &c)
{
	out << "(" << c.real << "," << c.imag << ")";
	return out;
}
int main()
{
	Complex c1(5,4),c2(2,10),c3;
	cout << "c1=" << c1 << endl;
	cout << "c2=" << c2 << endl;
	c3 = c1 - c2;
	cout << "c3=c1-c2=" << c3 << endl;
	c3 = c1 + c2;
	cout << "c3=c1+c2=" << c3 << endl;
	system("pause");
	return 0;
}

 运行截图

 

 分析:将运算符重载为类的非成员函数,就必须把操作数全部通过形参的方式传递给运算符重载函数。

 

posted @ 2019-10-26 18:10  Zzzxy  阅读(654)  评论(0编辑  收藏  举报