什么是运算符重载:对已有的运算符赋予多重含义
实现机制:
1、将制定的运算符表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参;
2、编译系统对重载运算符的选择,遵循函数重载的选择选择原则;
规则和限制:
1、不可以重载的运算:"." “.*” “::” “?:”
2、只能重载C++语言中已有的运算符,不可臆造新的
3、不改变原运算符的优先级和结合性
4、不能改变操作数个数;
5、经重载的运算符,其操作数中至少应该有一个是自定义类型
两种形式:
1、重载为类的非静态成员函数
2、重载为非成员函数(通常为友元函数)
声明形式:
函数类型 operator 运算符(形参){}
其中参数个数要求为:
1、重载为类成员函数时:参数个数=原操作数个数-1(除了后置++或–之外)(减1的原因是对象本身就是另一个操作数)
2、重载为非成员函数时,参数个数=原操作数个数,且至少应该有一个自定义类型的形参
运算符成员函数的设计
1、双目运算符B:
- 如果要重载运算符B为类成员函数,使之能够实现表达式
oprd1 B oprd2
,其中oprd1为A类对象,则B为应被重载为A类的成员函数,形参类型应该是oprd2所属的类型 - 经重载后,表达式
oprd1 B oprd2
相当于oprd1.operator B(oprd2)
如下举例所示,设计一个复数相加的程序,
class Complex {
public:
Complex(int _real, int _imag) :real(_real), imag(_imag) {};
Complex& operator + (const Complex& c) {
real += c.real;
imag += c.imag;
return *this;
}
int getReal() {
return real;
}
int getImag() {
return imag;
}
private:
int real;//实部
int imag;//虚部
};
int main() {
Complex c1(1, 1);
Complex c2(2, 2);
c1 = c1 + c2;
printf("c1的虚数为:%d + %dj", c1.getReal(), c1.getImag());
}
2、单目运算符U:
- 如果要重载U为类成员函数,使之能够实现表达式
U oprd
,其中oprd为A类的对象,则U应被重载为A类的成员函数,无形参 - 重载后,表达式
U oprd
相当于oprd.operator U()
3、后置单目运算符++和–
- 如果要重载后置运算符++和–为类成员函数,使之能够实现表达式
oprd++
或oprd--
,其中oprd为A类对象,则++或–应被重载为A类的成员函数且有一个int型形参(主要是用来区别于前置++或–,不必写形参名) - 经重载后,表达式
oprd++
相当于oprd.operator ++ (0);
举例如下,实现复数的实部和虚部自加
class Complex {
public:
Complex(int _real, int _imag) :real(_real), imag(_imag) {};
Complex& operator ++ () {
++real;
++imag;
return *this;
}
Complex operator ++ (int) {
Complex old = *this;
++(*this);
return old;
}
void showComplex() {
printf("%d + %dj\n", real, imag);
}
private:
int real;//实部
int imag;//虚部
};
int main() {
Complex c1(1, 1);
(++c1).showComplex();
(c1++).showComplex();
c1.showComplex();
}
/*输出:
2 + 2j
2 + 2j
3 + 3j
*/
从输出结果可以看出,复数的前置++和后置++都运行正确;
运算符非成员函数的设计
注意:
1、函数的形参代表依自左至右次序排列的各操作数;
2、后置单目运算符++和–的重载函数,形参列表要增加一个int,但不必写形参名
3、如果在运算符的重载函数中需要操作某类对象的私有成员,可以将此函数的声明为该类的友元。
运算符非成员函数:
1、双目运算符 B重载后,
表达式:oprd1 B oprd2
等同于 operator B(oprd1, oprd2)
前置单目运算符 B 重载后
表达式:B oprd
等同于 operator B(oprd)
后置单目运算符++和–重载后
表达式:oprd++
等同于 operator ++(oprd, 0)
举例如下:实现复数的连续输出
class Complex {
public:
Complex(int _real, int _imag) :real(_real), imag(_imag) {};
friend ostream& operator << (ostream& out, const Complex& c);
private:
int real;//实部
int imag;//虚部
};
ostream& operator << (ostream& out, const Complex& c) {
return out << c.real << " + " << c.imag << "j ";
}
int main() {
Complex c1(1, 1);
Complex c2(2, 2);
Complex c3(3, 3);
cout << c1 << c2 << c3;
}
/*输出:
1 + 1j 2 + 2j 3 + 3j
*/