注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。
测试环境:Ubuntu 10.10
GCC版本:9.2.0
一、需要解决的问题
1)下面的复数解决方案是否可行?
加法操作能作用在两个对象上吗(c3)—— 编译错误
编程实验
复数的加减法
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\n", c3.getA(), c3.getB());
return 0;
}
操作:
1) g++ 30-1.cpp -o 30-1.out编译正确,打印结果:
c3.a = 4, c3.b = 6
二、思考……
Add函数可以解决Complex对象相加的问题,但是Complex是现实世界中确实存在的复数,并且复数在数学中的地位和普通的实数相同。
为什么不能让+操作符也支持复数相加呢?
三、操作符重载
1)C++中的重载能够扩展操作符的功能
2)操作符的重载以函数的方式进行
3)本质:
- 用特殊形式的函数扩展操作符的功能
4)通过operator关键字可以定义特殊的函数(重点)
5)operator的本质是通过函数重载操作符
6)语法:
Type operator Sign(const Type& p1, const Type& p2)
{
Type ret;
//代码区
return ret;
}
Sign为系统中预定义的操作符,如:+,-,*,/,等
Type为类名
编程实验
操作符重载初探
30-2.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 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 = c1 + c2; // 找操作符重载函数,匹配参数:operator + (c1, c2)
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
操作:
1) g++ 30-2.cpp -o 30-2.out编译正确,打印结果:
c3.a = 4, c3.b = 6
2) 修改代码:
#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 = c1 + c2 + c2;//找操作符重载函数,匹配参数:operator + (c1, c2)
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
g++ 30-2.cpp -o 30-2.out编译正确,打印结果:
c3.a = 7, c3.b = 10
3) 测试:
int main()
{
Complex c1(1, 2);
Complex c2(3, 4);
Complex c3;
int c = (c1 + c2).getB();
printf("%d\n",c);
return 0;
}
编译正常,打印结果:
6
分析:
这种方式也可以调用?
7)可以将操作符重载函数定义为类的成员函数
- 比全局操作符重载函数少一个参数(左操作数)
- 不需要依赖友元就可以完成操作符重载
- 编译器优先在成员函数中寻找操作符重载函数(一旦找到了,不会调用全局的函数重载功能)
class Type
{
public:
Type operator Sign(const Type& p)
{
Type ret;
//代码区
return ret;
}
};
编程实验
成员函数重载操作符
30-3.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;
}
Complex operator + (const Complex& p) //左操作数是this参数,右操作数是p
{
Complex ret;
printf("Complex operator + (const Complex& p)\n");
ret.a = this->a + p.a;
ret.b = this->b + p.b;
return ret;
}
friend Complex operator + (const Complex& p1, const Complex& p2);
};
Complex operator + (const Complex& p1, const Complex& p2)
{
Complex ret;
printf("Complex operator + (const Complex& p1, const Complex& p2)\n");
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 = c1 + c2; // 等价c1.operator + (c2)
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
操作:
1) g++ 30-3.cpp -o 30-3.out编译正确,打印结果:
Complex operator + (const Complex& p)
c3.a = 4, c3.b = 6
分析:
编译器优先调用类中的重载操作。
小结
1)操作符重载是C++的强大特性之一
2)操作符重载的本质是通过函数扩展操作符的功能
3)operator关键字是实现操作符重载的关键
4)操作符重载遵循相同的函数重载规则
5)全局函数和成员函数都可以实现对操作符的重载
比如友元函数。