读书笔记(C++)————【重载操作符与转换】

时间:2021-12-21 17:49:29
//14.重载操作符与转换

//14.1 重载操作符的定义

//不能重载的操作符
:: .* . ?:

//重载操作符必须具有至少一个类类型或枚举类型的操作数

//优先级和结合性是固定的

//不再具备短路求值特性,重载&&和||不是好做法

//作为类成员函数的重载函数,形参比操作数少一,隐含this形参作为第一个操作数

//一般将算数和关系操作符定义为非成员,而将赋值操作符定义为成员

//也可以像普通函数一样调用重载操作符函数
cout << operator+(item1,item2) << endl;
//等效
cout << item1 + item2 << endl

//尽量避免重载 , & && || 操作符

//若重载算数操作符(+),应同时重载复合赋值符(+=)

//必须定义为成员的操作符:= [] () ->

//14.2 输入输出操作符

//Sale_item重载输出操作符,不应输出换行符
ostream&
operator<<(ostream& out,const Sales_item& s)
{
out << s.isbn << "\t" << s.units_sold << "\t"
<< s.revenue << "\t" << s.avg_price();
return out;
}

//IO操作必须为非成员函数,因为左操作数必须是类类型对象

//Sale_item重载输入操作符
istream&
operator<<(istream& in, Sales_item& s)
{
double price;
in >> s.isbn >> s.units_sold >> price;
if(in)
s.revenue = s.unit_sold * price;
else
s = Sale_item();//input failed:reset object to default state
return out;
}

//相等操作符
inline bool
operator==(const Sale_item& c1,Sale_item& c2)
{
return c1.units_sold == c2.units_sold &&
c1.revenue == c2.revenue &&
c1.same_isbn(c2);
}
inline bool
operator!=(const Sale_item& c1,Sale_item& c2)
{
return !(c1 == c2);
}

//14.4 赋值操作符

//赋值操作符可重载且必须返回*this引用

//14.6 成员访问操作符

//#include <iostream>
using namespace std;

class A{
public:
void action(){
cout << "Action in class A!" << endl;
}
};

class B{
A a;
public:
A* operator->(){
return &a;
}
void action(){
cout << "Action in class B!" << endl;
}
};

class C{
B b;
public:
B operator->(){
return b;
}
void action(){
cout << "Action in class C!" << endl;
}
};

int main(int argc, char *argv[])
{
C* pc = new C;
pc->action();
C c;
c->action();
getchar();
return 0;
}
/*上面代码输出结果是:
*Action in class C!
*Action in class A!
*/

//14.7 自增操作符和自减操作符

//调用后置++需要给出一个整形实参
c.operator++(0);

//调用操作符()和函数对象,必须声明为成员函数。
class absInt
{
int operator()(int val)
{
return val > 0 : -val : val;
};
};

//14.8.1 将函数对象用于标准算法

//函数对象比函数更灵活,容易修改程序以根据其他值进行测试。例:
//函数:
bool GT6(const string &s)
{
return s.size() >= 6;
}
vector<string>::size_type wc =
count_if(words.begin(),words.end(),GT6);
//函数对象:
class GT_cls
{
public:
GT_cla(int val = 0):bound(val){}
bool operator()(const string &s)
{
return s.size() >= bound;
}
private:
string::size_type bound;

};
cout << count_if(words.begin(),words.end(),GT_cla(6))
<< " words 6 characters or longer" << endl;
//14.8.2 标准库定义的函数对象#include<functional>

//表 14 - 3 标准库函数对象
类型 函数对象 所应用的操作符
算术函数对象类型 plus<Type> +
minus<Type> - //接受一个实参
multiplies<Type> *
divides<Type> /
modulus<Type> %
negate<Type> -
关系函数对象类型 equal_to<Type> ==
not_equal_to<Type> !=
greater<Type> >
greater_equal<Type> >=
less<Type> <
less_equal<Type> <=
逻辑函数对象类型 logical_and<Type> &&
logical_or<Type> |
logical_not<Type> ! //接受一个实参

//每个类都定义了应用名操作的调用操作符
plus<int> intAdd;
int sum = intAdd(10,20);//sum = 30;

//函数对象常用于覆盖算法使用的默认操作符。例如,sort默认使用
//operator<按升序对容器进行排序。为了按降序对容器进行排序,
//可以传递函数对象greater。该类将产生一个调用操作符,调用基础对象的大于操作符。
//如果svec是一个vector<string>对象,以下代码将降序排列
sort(svec.begin(),svec.end(),greater<string>());

//14.8.3 函数对象的函数适配器

//两类:1.绑定器 bind1st bind2nd
// 2.求反器 not1(求反一元函数对象真值) not2(求反二元函数真值)

//计算一个容器中所有小于或等于10的值,适配器返回一个函数对象
count_if(vec.begin(),vec,end(),bind2nd(less_equal<int>(),10)));
count_if(vec.begin(),vec,end(),not1(bind2nd(less_equal<int>(),10))));

//14.9.2 转换操作符

//不允许转换数组或函数,可转换为指针以及引用
class SmallInt
{
public:
SmallInt(int i = 0):val(0)
{
if(i < 0 || i > 255)
throw std::out_of_range("Bad SmallInt Initialize")
}
operator int() const{return val;}
private:
std::size_t val;
};


//使用类类型转换
SmallInt si;
double dval;
si >= dval; //si converted to int and then convert to double

if(si) //si converted to int and then convert to bool

//只能应用一个类类型转换

//它可以转换为SmallInt,但不能转换成Int
class Intergral
{
Intergral(int i = 0):val(i){}
operator SmallInt() const {return val % 256;}
private:
std::size_t val;
};

int calc(int);
Integral inVal;
SmallInt si(intVal); //ok
int i = calc(si) //ok
int j = calc(intVal) //error

//标准转换可放在类类型转换之前

//14.9.3 实参匹配和转换

//待续

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//

//