这篇笔记的内容是重载运算与类型转换。
这是一个从越来越底层的角度去理解一个更抽象高层的知识。
一、基本介绍与引入
1)直接调用一个重载的运算符函数
这告诉我们可以直接调用重载后的运算符函数的。举个例子
class test {
public:
test(int v) {
val = v;
};
test& operator+(int a) {
val += a;
return *this;
}
int val;
};
void main()
{
test a = 1;
a.operator+(2);
a=a+3;
cout << a.val << endl;
}
2)某些运算符不应该被重载
3)使用与内置类型一致的含义
加号的重载就让其保持加号的含义而不是减号。
4) 赋值和复合赋值运算符
5)选择作为成员或者非成员
二、输入和输出运算符
1.重载输出运算符<<
1)Sale_data的输出运算符
2)输出运算符尽量减少格式化操作
3)输入输出运算符必须是非成员函数
这点非常值得注意。
2.重载输入运算符
1)Sale_data的输入运算符
2)输入时的错误
3)标识错误
三、算术和关系运算符
关于 为什么你认为定义 operator+ 来调用 operator+= 而不是反过来更有效?,可参考:c++ - Why is it more efficient to define operator+ to call operator+= rather than the other way around? - Stack Overflow
1.相等运算符
2.关系运算符
四、赋值运算符
1)复合赋值运算符
五、下标运算符
六、递增和递减运算符
这章到目前位置,重载必须为成员函数的有:赋值运算符、输入输出运算符,其他的可以不用。
1.定义前置递增/递减运算符
2.区分前置和后置运算符
后置递增运算符要小心。注意区别。
3.显式地调用后置运算符
七、成员访问运算符
理解的有点困难,既然如此,那还是不要随便重载成员访问运算符了。
对箭头运算符返回值的限定
关于成员访问运算符的更多内容可参考:C++ 类成员访问运算符 -> 重载 | 菜鸟教程
八、函数调用运算符
这种重载方式在学习primer之前是没有听过的。并且函数对象也是头一回听到。
1)含有状态的函数对象类
1. lambda是函数对象
从这理解的话,lambda表达式会隐式转换为一个函数对象。
2.标准库定义的函数对象
1)在算法中使用标准库函数对象
3.可调用对象与function
1)不同类型有相同的调用形式
2)标准库function类型
使用function可以使不同的函数类型能有相同的调用形式。
3)重载的函数与function
九、重载、类型转换与运算符
抓住两个要点:转换构造函数、类型转换运算符
一个构造函数接收一个不同于其类类型的形参,可以视为将其形参转换成类的一个对象。像这样的构造函数称为转换构造函数。
转化构造函数可参考:C++转换构造函数(详解版)
1.类型转换运算符
1)定义含有类型转换运算符的类
不是所有的类都要弄类型转换,而是尽量当有明显的映射关系再设置转换。
2)类型转换运算符可能产生运算结果
3)显式的类型转换运算符
举个例子:
class test {
public:
test(int v) {
val = v;
};
explicit operator int() const { return val; }
int val;
};
void main()
{
test t = 3;
if (t == 3)cout << "333" << endl;//报错
if ((int)t == 3)cout << "333" << endl;//可以
if (static_cast<int>(t) == 3)cout << "333" << endl;//可以
}
3)转换为bool
2.避免有二义性的类型转换
这一段话初看起来会比较抽象,等后面的看明白了再回头了看这个就会好理解多了。
1)实参匹配和相同的类型转换
2)二义性与转换目标为内置类型的多重类型转换
3)重载函数与转换构造函数
4)重载函数与用户定义的类型转换
3.函数匹配与重载运算符
截一个报错的图:
最后,重载带来的二义性问题感觉都很隐蔽,不容易察觉,需要好好注意。