(七)C++基础之运算符重载(一)
一、C++运算符重载之使用规则
1.1、运算符重载的意义
所谓重载,就是重新赋予新的含义 ,函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。
所以运算符也可以重载,例如我们经常使用的 << 左移运算符,被重新赋予别的功能。
运算符重载的本质是函数重载。
运算符重载的个格式:
函数类型 operator 运算符名称(形参表列)
{
重载实体;
}
1.2、运算符重载实例
我们这边使用 + 进行一个进行复数的加法。
代码如下:
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(int real, int imaginary)
{
this->real = real;
this->imaginary = imaginary;
}
void print(void)
{
cout << this->real << "+" << this->imaginary << "i" << endl;
}
friend Complex operator+(Complex &c1, Complex &c2);
private:
int real; //实数
int imaginary; //虚数
};
//全局定义加号运算符
Complex operator+(Complex &c1, Complex &c2)
{
Complex temp(0,0);
temp.real = c1.real + c2.real;
temp.imaginary = c1.imaginary + c2.imaginary;
return temp;
}
int main(void)
{
Complex c1(1,2);
Complex c2(1, 2);
Complex c3(0, 0);
c3 = c1 + c2;
c3.print();
return 0;
}
运行结果:
主要是定义复数的相加。
这种方式采用类外定义的全局函数,也可以在类里面进行定义。
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(int real, int imaginary)
{
this->real = real;
this->imaginary = imaginary;
}
void print(void)
{
cout << this->real << "+" << this->imaginary << "i" << endl;
}
Complex operator+(Complex &c2)
{
Complex temp(0, 0);
temp.real = this->real + c2.real;
temp.imaginary = this->imaginary + c2.imaginary;
return temp;
}
private:
int real; //实数
int imaginary; //虚数
};
int main(void)
{
Complex c1(1,2);
Complex c2(1, 2);
Complex c3(0, 0);
c3 = c1 + c2;
c3.print();
return 0;
}
运行结果和上面一样,但是如果在类里面写就可以避免友元申明了,所以在类里面定义的话可能会稍微好点,不会破坏类的封装性。
1.3、运算符重载
1、可以进行重载的运算符:
但是发现太多了,我们可以记忆不能进行重载的运算符。
2、不能重载的运算符:
不能重载的运算符只有四个,分别是 . .* :: ?:
所以我们可以单独记忆这四个不能重载的运算符,那么其余的运算符就意味着可以进行重载。
1.4、运算符重载规则
(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
例如,有人觉得 BASIC 中用 “* * ” 作为幂运算符很方便,也想在 C++中将 “* *”定义为幂运算符,用“ 3**5”表示3^5,这是不行的。
(2)重载不能改变运算符运算对象(即操作数)的个数。
如,关系运算符“ >”和“ <”等是双目运算符,重载后仍为双目运算符,需要两个参数。运算符” +“,” -“,” *“,” &“等既可以作为单目运算符,也可以作为双目运算符,可以分别将它们重载为单目运算符或双目运算符。
(3)重载不能改变运算符的优先级别。
例如” *“和” /“优先级高于” +“和” -“,不论怎样进行重载,各运算符之间的优先级不会改变。有时在程序中希望改变某运算符的优先级,也只能使用加括号的方法 强制改变重载运算符的运算顺序。
(4)重载不能改变运算符的结合性。
如,复制运算符” =“是右结合性(自右至左),重载后仍为右结合性。
(5)重载运算符的函数不能有默认的参数。
否则就改变了运算符参数的个数,与前面第(2)点矛盾。
(6)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。
也就是说,参数不能全部是 C++的标准类型,以防止用户修改用于标准类型数据成员的运算符的性质,如下面这样是不对的:
复制代码 代码如下:
int operator + (int a,int b)
{
return(a-b);
}
原来运算符+的作用是对两个数相加,现在企图通过重载使它的作用改为两个数相减。如果允许这样重载的话,如果有表达式 4+3,它的结果是 7 还是 1 呢?显然,这是绝对要禁止的。
(7)用于类对象的运算符一般必须重载,但有两个例外,运算符” =“和运算符” &“不必用户重载。
复制运算符” =“可以用于每一个类对象,可以用它在同类对象之间相互赋值。因 为系统已为每一个新声明的类重载了一个赋值运算符,它的作用是逐个复制类中的数据 成员地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
但是有一个例外对于等号运算符=,如果类中有指针需要开辟空间的话,需要自己实现运算符=的操作函数,进行深拷贝,而不是浅拷贝,否则容易出问题。
(8)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。
例如,我们会去重载” +“以实现对象的相加,而不会去重载” +“以实现对象相减的功能,因为这样不符合我们对” +“原来的认知。
(9)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非
类 的成员函数也不是友元函数的普通函数.