C++学习笔记之运算符重载

双目运算符:

 1 #include <iostream>
 2 using namespace std;
 3 class Complex {
 4 public:
 5     Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { } //默认构造函数虽说是默认,但是如果给了参数也能调用,是一个好习惯
 6     
 7     Complex operator+(const Complex& c2) const;//+
 8 
 9     Complex operator+(int& a) const;//复数和实数
10     
11     Complex operator - (const Complex& c2) const;//-
12 
13     void display() const;   //输出复数
14 private:
15     double real;    //复数实部
16     double imag;    //复数虚部
17 };
18 
19 Complex Complex::operator +(const Complex & c2) const { //复数+
20     return Complex(real + c2.real, imag + c2.imag);
21 }
22 
23 Complex Complex::operator +(int& a) const {//复数和实数+
24     a++;
25     return Complex(real + a, imag );
26 }
27 
28 Complex Complex::operator-(const Complex& c2) const {//复数-
29     return Complex(real - c2.real, imag - c2.imag);
30 }
31 
32 void Complex::display() const {
33     cout << "(" << real << ", " << imag << ")" << endl;
34 }
35 
36 int main() {
37     Complex c1(5, 4), c2(2, 10), c3;
38     int b = 5;
39     cout << "c1 = "; c1.display();
40     cout << "c2 = "; c2.display();
41     c3 = c1 - c2;   //使用重载运算符完成复数减法
42     cout << "c3 = c1 - c2 = "; c3.display();
43     c3 = c1 + c2;   //使用重载运算符完成复数加法
44     cout << "c3 = c1 + c2 = "; c3.display();
45     c3 = c1 + b;    //这里是复数和实数相加,注意(复数和int变量相加)和(复数直接加数c3=c1+5)的区别,后者编译器会把 5 当成复数再次生成一个复数类的对象,但是只有一个参数,也就是实部,然后进行复数类相加
,原因是写了默认的构造函数(上面黄色),我怀疑是加法函数的顺序问题,但试了一下,发现并不是,终究还是构造函数的问题,下面会给出后面这种方式的代码
46 cout << "c3 = c1 + c2 = "; c3.display(); 47 return 0; 48 }

想要让  c3=c1+5 调用的函数是复数+实数的代码(黄色是不用的地方):

 1 #include <iostream>
 2 using namespace std;
 3 class Complex {
 4 public:
 5     Complex() {};//默认构造函数,并不初始化赋值
 6     Complex(double r, double i) : real(r), imag(i) { } 
 7     
 8     Complex operator+(const Complex& c2) const;//+
 9 
10     Complex operator+(int a) const;//复数和实数
11     
12     Complex operator - (const Complex& c2) const;//-
13 
14     void display() const;   //输出复数
15 private:
16     double real;    //复数实部
17     double imag;    //复数虚部
18 };
19 
20 Complex Complex::operator +(const Complex & c2) const { //复数+
21     return Complex(real + c2.real, imag + c2.imag);
22 }
23 
24 Complex Complex::operator +(int a) const {//复数和实数+
25     a++;
26     return Complex(real + a, imag );
27 }
28 
29 Complex Complex::operator-(const Complex& c2) const {//复数-
30     return Complex(real - c2.real, imag - c2.imag);
31 }
32 
33 void Complex::display() const {
34     cout << "(" << real << ", " << imag << ")" << endl;
35 }
36 
37 int main() {
38     Complex c1(5, 4), c2(2, 10), c3;//c3 调用默认构造函数,垃圾数据
39     int b = 5;
40     cout << "c1 = "; c1.display();
41     cout << "c2 = "; c2.display();
42     c3 = c1 - c2;   //使用重载运算符完成复数减法
43     cout << "c3 = c1 - c2 = "; c3.display();
44     c3 = c1 + c2;   //使用重载运算符完成复数加法
45     cout << "c3 = c1 + c2 = "; c3.display();
46     c3 = c1 + 5;
47     cout << "c3 = c1 + c2 = "; c3.display();
48     return 0;
49 }

虽然后面解决了这种问题,但是我也发现了这种直接通过对象 运算符重载计算 的漏洞,所以我强烈建议对象之间的操作不要直接通过数字,而是通过对象和对象的操作从而使得能够按照自己的想法运行,虽然直接通过数字可以,但是其构造函数明显是不合理的(因为默认构造函数并没有给默认参数,而是垃圾数据,C3就是例子)

 

 为了解决这种情况,我们提出了非成员函数解决这个问题(之前的方法是调用成员函数)那这两种方法有什么区别?

如果要重载 B 为类成员函数,使之能够实现表达式 oprd1 B oprd2,其中 oprd1 为A 类对象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。经重载后,表达式 oprd1 B oprd2 相当于 oprd1.operator B(oprd2),这里形参少一个,因为这个类的对象就是其中一个操作数

而在非成员函数中:参数个数=原操作数个数,表达式oprd1 B oprd2,等同于operator B(oprd1,oprd2 ),因为并不是成员函数,所以只是返回的类型是这个类型,而形参表中首先必须要有自定义的类型,就像调用一个函数一样

如果在运算符的重载函数中需要操作某类对象的私有成员,可以将此函数声明为该类的友元。

posted @ 2020-01-02 02:03  深海的石头  阅读(127)  评论(0编辑  收藏  举报