1. 复数类需要解决的问题
——下面的复数解决方案是否可行?
不可行,+ 操作符只提供对C++ 基本数据类型的运算,不支持类的相加运算。
【编程实验】复数的加法操作 30-1.cpp
#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 ", c3.getA(), c3.getB()); return 0; }
运行结果:
思考:Add 函数可以解决Complex 对象相加的问题,但是 Comples 是现实世界中确实存在的复数,并且复数在数学中的地位和普通的实数相同。
为什么不让 + 操作符也支持复数相加呢?
2. 操作符重载
(1)C++中的重载能够扩展操作符的功能
(2)操作符的重载以函数的方式进行,本质上是用特殊形式的函数扩展操作符的功能
(3)通过operator关键字可以定义特殊函数,operator的本质是通过函数来重载操作符
(4)语法: Type operator Sign(const Type& p1, const Type& p2); //Sign如+、-、*等
【编程实验】操作符重载初探
#include <stdio.h> class Complex { private: 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); //方式二:通过全局函数重载“+”操作符实现复数相加 friend Complex operator + (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; } //全局重载操作符+ 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 = Add(c1, c2); //方式一调用。缺点是无法写成:c1 + c2的形式; //方式二的调用 //Complex c3 = operator+(c1, c2);//把“opertor+”当成函数名一样的调用 Complex c3 = c1 + c2; //更直观,本质上是调用“operator+”这个函数 printf("c3.a = %d, c3.b = %d ",c3.getA(), c3.getB()); return 0; }
运行结果:
3. 可将操作符重载函数定义为类的成员函数
(1)比全局操作符重载函数少一个参数(左操作数)
(2)不需要依赖友元就可以完成操作符重载
(3)编译器优先在成员函数中寻找操作符重载函数(截图)
【编程实验】成员函数重载操作符 30-3.cpp
#include <stdio.h> class Complex { private: 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); //方式二:通过全局函数重载“+”操作符实现复数相加 friend Complex operator + (const Complex& p1, const Complex& p2); //方式三:通过成员函数实现“+”操作符的重载 Complex operator+(const Complex& p) //参数少了一个左操作数! { Complex ret; ret.a = this->a + p.a; ret.b = this->b + p.b; return ret; } }; //全局普通函数 Complex Add(const Complex& p1, const Complex& p2) { Complex ret; ret.a = p1.a + p2.a; ret.b = p1.b + p2.b; return ret; } //全局重载操作符+ 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 = Add(c1, c2); //方式一调用。缺点是无法写成:c1 + c2的形式; //方式二的调用 //Complex c3 = operator+(c1, c2);//把“opertor+”当成函数名一样的调用 //Complex c3 = c1 + c2; //更直观,本质上是调用“operator+”这个函数 //方式三的调用 //Complex c3 = c1.operator+(c2);//把“opertor+”当成函数名一样的调用 Complex c3 = c1 + c2; //优先选择成员函数,而不是全局的operator+ printf("c3.a = %d, c3.b = %d ",c3.getA(), c3.getB()); return 0; }
运行结果:
4. 小结
(1)操作符重载是C++的强大特性之一,其本质是通过函数扩展操作符的功能
(2)operator关键字是实现操作符重载的关键
(3)操作符重载遵循相同的函数重载规则
(4)全局函数和成员函数都可以实现对操作符的重载,但编译器优先选择通过成员函数实现的操作符重载函数