C++ 重载运算
运算符重载
C++ 使用 operator
关键字来重载运算符
1 | 返回值类型 operator运算符(参数) |
- 重载后,操作符至少有一个是用户定义的类型
- 不能违反运算符原本的句型规则,
% x
是不行的 - 不能创建新的运算符
- 不能修改运算符优先级
大多数运算符都能通过成员或非成员函数进行重载,但
=, (), [], ->
只能通过成员函数进行重载
以 =
为例
1 |
|
这是一种特殊情况,如果没有使用类成员函数来重载
=
,那么类可以调用匹配的构造函数,用非成员函数来重载
=
就会和构造函数冲突,因此 =
只能通过成员函数进行重载
友元
- 友元函数
- 友元类
- 友元成员函数
假设现在有类成员函数重载 *
A = B * 2.75;
就会被转换为
A = B.operator(2.75);
但是 A = 2.75 * B
却是不可行的
其中一种解决方法是使用非成员函数,可以按所需的顺序获得操作数,但是需要将类成员变量改为
public
,这是不安全的,然而友元函数这一特殊的非成员函数可以访问类的私有成员
创建友元
首先将友元函数的原型放在类声明中,关键字为 friend
1 | friend Time operator*(double m, const Time &t); |
- 虽然函数在类声明中声明,但不是成员函数
- 虽然不是成员函数,但与成员函数的访问权限相同
常用友元:重载 << 运算符
对 <<
进行重载,能与 cout
输出对象内容
最初 <<
是位左移运算符,但在 ostream
中对该运算符进行了重载,能够识别所有的 C++ 基本类,这是因为
ostream
类声明中都包含了相应的重载
operator<<()
定义
如果用类成员函数来重载 <<
,则只能这样
qwt << cout;
,所以可以使用友元函数来重载运算符
1 | void operator<<(ostream &os, const Time &t) |
该函数是 Time 类的友元而不是 ostream 类的友元,因为该友元函数可以直接访问 Time 对象的私有成员
但是该实现方法也有问题
1 | cout << "Trip time: " << trip << " (Tuesday)\n"; // can't do |
举个例子
1 | int x = 5; |
这意味着先执行 cout << x
,cout
是
ostream 对象,cout << x
也是返回 osteam
对象,所以这里的 <<
都是 osteam 类的重载运算符
因此可以修改友元函数,使其返回 ostream 类对象的引用
1 | ostream &operator <<(ostream &os, const Time &t) |
类的转换
假设类 Stonewt
有 Stonewt(double)
构造函数,就可以将构造函数用作 自动类型转换 函数
1 | Stonewt myCat; |
这在符号重载中也提到过
这是 隐式转换,会使用构造函数
Stonewt(double)
创建一个临时的 Stonewt
对象,并将 19.6
作为初始化值,然后采用逐成员赋值方式将该临时对象的内容复制到
myCat
中
只有接受一个参数的构造函数才能作为转化函数,但如果提供默认值,也可以
1 | Stonewt(int stn, double lbs = 0); |
C++ 新增关键字 explicit
可以关闭这种自动特性
1 | explicit Stonewt(double lbs); // 声明构造函数 |
explict
仍然支持显示转换