常忘常看,记录下来以备后忘
关键字operator和其后要定义的运算符号共同组成。除了operator()之外,其他不能重载运算符不能有默认参数。
一元运算符只传递一个参数,二元运算符传递两个参数给函数。
一个运算符函数是成员函数,this绑定到左侧运算对象,所以成员运算符(显式)参数数量比运算对象少一个
note:
内置类型不可以重载运算符,且只能重载已有运算符,不能被重载的运算符包括 :: .* . ?:
直接用运算符或者直接调用函数
data1 + data2 ,也可以operator(data1, data2)
成员函数时也可以写成data1+= data2 data1.opterator+(data2),其中+= 这个二元操作符的第一个参数是隐式传入的data1
& , 等运算符是有特殊意义的,不建议重载
本质上运算符重载是一次函数调用,所以无法保留求值顺序 短路求值属性,所以不建议重载
设计类时,考虑类将提供哪些操作,之后再思考把类设成普通函数还是重载的运算符。
某些时候必须作为成员,但是有些情况,普通函数比成员更好。
通常情况下,第一个参数应该是非常量ostream对象的引用。非常量是因为会改变对象状态,引用是因为ostream对象无法复制
输出运算符应该尽量减少格式化操作,尤其不会打印换行符
通常情况下,它应该主要负责输出内容而非格式
**输入输出运算符必须是非成员函数,否则左侧对象将是我们类的一个对象,我们的格式将会变成data << out。。**如果定义成正常输出方式,我们又无法有来看中stream成员增加函数
所以我们要将输入输出定义成非成员函数,当然因为我们要读写类的非公有数据成员,所以一般要声明为友元
通常第一个参数是读取流的引用,第二个参数是非常量的对象的引用,返回值是给定流的引用。
istream & operator >> (istream& is, Data& data)
{
double price;
is >> data.no >> data.sold >> price;
if(is)
{
data.revenue = data.sold * price;
}
else
{
data = Data();
}
}
注意:输入运算符必须处理可能失败的情况
一般会定义成非成员函数,因为一般不需用改变运算对象的状态,所以形参都是常量的引用。
如果一个类含有两个对象比较相等的操作,应该定义operator== ,因为符合用户习惯
定义了opterator== , 运算符应该能判定一组给定对象中是否含有重复数据
通常情况下,相等运算符应该有传递性
如果定义了operator==,也应该定义operator !=
operator==,operator != 应该一个运算符委托给另外一个去做,比如,operator != 中返回 ! operator== 的操作
本内容参照c++ primer第四版内容
定义了==的通常也会定义小于运算符,因为关联容器和一些算法需要用到小于运算符,所以定义<比较有用
和拷贝赋值以及移动赋值一样,重载的赋值函数,应当先释放当前内存空间,然后再创建一片新空间。
必须是成员函数,通常会定义两个版本,一个是返回普通引用,一个返回类的常量成员并返回常量引用
前置operator++() 后置operater++(int) 参数仅用来区分前置后置运算符
如果重载了函数调用运算符(),则可以想使用函数一样,使用该类的对象
struct abrInt
{
int operator()(int) const
{
return val < 0 ? -val : val;
}
}
int i = 19;
abrInt absObj;
absObj(i);
如果类定义了调用运算符,该类对象称为函数对象。即使absObj只是一个对象,也能"调用"该对象。实际上是调用重载的调用运算符。