运算符重载
什么是运算符重载
使系统内置的运算符可以用于类类型
例如:类A的对象a1、a2、a3,可以执行
a3 = a1 + a2;
运算符重载的方法
运算符重载就是写一个函数解释某个运算符在某个类中的含义
关键问题
如何使编译器能自动找到重载的这个函数
解决方案
函数名必须要体现出和某个被重载的运算符的联系。
C++中规定,重载函数名为 operator@. 其中,@为要重载的运算符
重载“+”运算符,该重载函数名为operator+
重载赋值运算符,函数名为operator=
函数原型 运算符的重载不能改变运算符的运算对象数
形式参数个数(包括成员函数的隐式指针this)及类型与运算符的运算对象相符
返回值与运算结果值类型一致
成员函数vs全局函数
大多数运算符的重载函数可以写成成员函数,也可以写成全局函数
重载成全局函数 函数原型与运算符与完全相符 最好将此函数设为友员函数
重载成成员函数 形式参数个数比运算符的运算对象数少1。这是因为成员函数有一个隐含的参数this 隐含参数this是第一个形式参数
重载实例
重载实例
为rational类增加“+”和“*”以及“==”比较的重载函数,用以替换现有的add和multi函数
方案一:重载成成员函数
class Rational { private: int num; int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) { num = n; den = d; } Rational operator+(const Rational &r1) const; Rational operator*(const Rational &r1) const; bool operator==(const Rational &r1) const; void display() { cout << num << '/' << den; } };
函数实现
Rational Rational::operator+(const Rational &r1) const { Rational tmp; tmp.num = num * r1.den + r1.num * den; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; } Rational Rational::operator*(const Rational &r1) const { Rational tmp; tmp.num = num * r1.num; tmp.den = den * r1.den; tmp.ReductFraction(); return tmp; } bool Rational::operator==(const Rational &r1) const { return num == r1.num && den == r1.den; }
方案二:重载成友员函数
class Rational { friend Rational operator+(const Rational &r1, const Rational &r2); friend Rational operator*(const Rational &r1, const Rational &r2); friend bool operator==(const Rational &r1, const Rational &r2); private: int num; int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) { num = n; den = d; } void display() { cout << num << '/' << den; } };
函数实现
Rational operator+(const Rational &r1, const Rational &r2) { Rational tmp; tmp.num = r1.num * r2.den + r2.num * r1.den; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; } Rational operator*(const Rational &r1, const Rational &r2) { Rational tmp; tmp.num = r1.num * r2.num; tmp.den = r1.den * r2.den; tmp.ReductFraction(); return tmp; }
其他函数实现略
重载后有理数类的使用
int main() { Rational r1(1, 6), r2(1, 6), r3; r3 = r1 + r2; r1.display(); cout << " + "; r2.display(); cout << " = "; r3.display(); cout << endl; r3 = r1 * r2; r1.display(); cout << " * "; r2.display(); cout << " = "; r3.display(); cout << endl; return 0; } //题目描述: //补全Int类,使得程序的输出为: //1 //2 //3 //4 //5 #include <iostream> using namespace std; class Int { static int addtime; public: Int(int x) {} friend int operator+(const Int &r1, const Int &r2) { return ++addtime; } }; int Int::addtime = 0; int main() { Int a(1), b(1), c(1); cout << a + a << endl; cout << b + b << endl; cout << b + c << endl; cout << c + c << endl; cout << a + a << endl; }
组合
对象成员
聚集关系,是一种部分和整体的关系,即has-a的关系
组合的目的:简化创建新类的工作,让创建新类的程序员不需要过多地关注底层的细节,可以在更高的抽象层次上考虑问题,有利于创建功能更强的类。
继承
c++派生类定义的格式如下:
class 派生类名:继承方式 基类名{ 新增加的成员声明; };
继承方式可以是public、private和protected
派生类中基类成员的访问特性
多态性
多态性有两种实现方式:编译时的多态性和运行时的多态性
运算符重载和函数重载属于编译时的多态性
虚函数属于运行时的多态性