第30课 操作符重载
下面的程序可行吗
class Complex
{
public:
int a;
int b;
};
int main()
{
Complex c1 = {1,2};
Complex c2 = {3,4};
Complex c3 = c1 + c2;
return 0;
}
现在这程序肯定编译不过,因为现在的+号运算符作用在两个对象之间。
可以这样解决:
class Complex
{
public:
int a;
int b;
};
Complex add(const Complex& p1, const Complex& p2)
{
Complex ret;
ret.a = p1.a + p2.a;
ret.b = p1.b + p2.b;
return ret;
}
int main()
{
Complex c1 = {1,2};
Complex c2 = {3,4};
Complex c3 = add(c1,c2);
return 0;
}
这种方案倒是能够实现复数相加,但是将类的成员变量定义为公有的,暴露给用户,显得太不专业。
方案二:
#include <stdio.h>
class Complex
{
int a;
int b;
public:
Complex(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
}
int getA()
{
return a;
}
int getB()
{
return b;
}
friend Complex Add(const Complex& p1, const Complex& p2);
};
Complex Add(const Complex& p1, const Complex& p2)
{
Complex ret;
ret.a = p1.a + p2.a;
ret.b = p1.b + p2.b;
return ret;
}
int main()
{
Complex c1(1, 2);
Complex c2(3, 4);
Complex c3 = Add(c1, c2); // c1 + c2
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
以上程序利用了友元的特性,较好的解决了复数相加的问题。但是并不完美。完美的解决方案就是直接c3 = c1 + c2
操作符重载
C++中的重载能够扩展操作符的功能
操作符重载以函数的方式进行
本质:
用特殊形式的函数扩展操作符的功能
通过operator关键字可以定义特殊的函数
operator的本质是通过函数重载操作符
语法:
Type operator Sign(const Type p1, const Type p2)
{
Type ret;
return ret;
}
Sign 为系统中预定义的操作符,如 +,-,*,/等。
#include <stdio.h>
class Complex
{
int a;
int b;
public:
Complex(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
}
int getA()
{
return a;
}
int getB()
{
return b;
}
friend Complex operator + (const Complex& p1, const Complex& p2);
};
Complex operator + (const Complex& p1, const Complex& p2)
{
Complex ret;
ret.a = p1.a + p2.a;
ret.b = p1.b + p2.b;
return ret;
}
int main()
{
Complex c1(1, 2);
Complex c2(3, 4);
// Complex c3 = operator + (c1, c2); // 编译可以通过。
Complex c3 = c1 + c2;//编译器看到是两个对象相加,第一反应是我办不到,但是编译器会去看看有没有用重载的概念来扩展操作符的功能呢?于是编译器就尝试的去找有没有operator +这个函数。找到这个函数后,编译器会去看看操作符的左操作数和右操作数能否和函数的参数相匹配。
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
进一步分析:
可以将操作符重载函数定义为类的成员函数
-比全局操作符重载函数少一个参数(左操作数)
-不需要依赖友元就可以完成操作符重载
-编译器优先在成员函数中寻找操作符重载函数
(假设写了成员函数的重载,又写了全局函数的重载)
class Type
{
public:
Type operator Sign(const Type& p)
{
Type ret;
return ret;
}
};
解析:比全局操作符重载函数少一个参数(左操作数)
只是看上去少了,其实并没有少。成员函数中有一个隐藏的参数,this指针。因此,当使用成员函数来重载操作符时,
看上去少了一个参数,少了的那个参数是左操作数,其实不然。因为隐藏的那个this参数就可以充当左操作数的角色了。
#include <stdio.h> class Complex { int a; int b; public: Complex(int a = 0, int b = 0) { this->a = a; this->b = b; } int getA() { return a; } int getB() { return b; } Complex operator + ( const Complex& p) { Complex ret; ret.a = this.a + p.a; ret.b = this.b + p.b; return ret; }
}; int main() { Complex c1(1, 2); Complex c2(3, 4); // Complex c3 = operator + (c1, c2); Complex c3 = c1.operator + (c2); 等价于Complex c3 = c1 + c2; printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB()); return 0; }
小结:
操作符重载是C++的强大特性之一
操作符重载的本质是通过函数扩展操作符的功能
operator关键字是实现操作符重载的关键
操作符重载遵循相同的函数重载规则
全局函数和成员函数都可以实现对操作符的重载