//1.当运算符作用于类类型运算对象时,可以通过运算符重载重新定义该运算符的含义。明智的使用运算符重载能令程序更加易于编写和阅读。

//2.重载的运算符是具有特殊名字的函数,它们由关键字operator和其后要定义的运算符号共同组成。和其它函数一样,重载的运算符也包含返回类型,参数列表以及函数体。

//3.除了重载函数调用符之外,其余的重载运算符不能含有默认实参。

//4.如果运算符函数是成员函数,则其左侧运算对象绑定到隐式的this指针。
// 对于运算符函数来说,它或者是类的成员,或者至少含有一个类类型的参数。即无法改变运算符作用于内置对象时候的操作。 //5.对于重载的运算符来说,其优先级和结合律是无法被改变的。 //6.某些运算符指定了运算对象的求值顺序。因为使用重载的运算符本事是一次函数调用,所以这些运算对象求值顺序的规则无法应用到重载的运算符上。
// && || , 的求值顺序规则无法保留下来。 && || 的短路求值属性也无法保留,因此一般不对这些运算符进行重载。
// C++语言已经定义了, 和 & 用于类类型对象时候的特殊含义,这一点与大多数运算符都不相同,所以一般也不要进行重载。 //7.当重载了==运算符的时候,一般也需要重载!=。重载了<则一般也要重载>。若重载了算数运算符或者位运算符,则最好也提供其复合版本。 //8.当我们定义重载的运算符的时候,必须首先决定是将其声明为类的成员函数还是类的非成员函数。其区别是:类的成员函数版本的重载运算符其左侧操作对象必须是该类的对象。
// 一般来说 = () [] -> 必须定义为类的成员函数版本。
// 重载的复合运算符一般来说作为类的成员函数,但非必须。
// 改变对象状态的运算符或与给定类型密切相关的运算符,比如 递减, 递增, 解引用 通常为作为类的成员函数。
// 具有对称性的运算符可能转换任意一端的运算对象,例如 算数 相等性 关系 位运算符等,通常应该是类的非成员函数(需按照类类型对象的位置,定义多个版本的重载运算符函数)。
// 尽量使重载的运算符与其内置的版本表现一致。 //9.如果存在唯一一种可靠的<定义,则应该考虑为这个类定义<运算符(关联容器和一些算法需要此运算符)。如果类同时还包含==,则当且仅当<定义和==结果是一致的时候才定义<(这里的结果一致的意思是:当不能满足==的时候,2个对象必须有一个是<另一个的)。 //10.下标运算符的内置版本是返回引用类型,所以其重载类型最好也返回引用类型,而且通常定义下标运算符的常量版本和非常量版本,防止作用于一个常量对象时不会给其返回的对象赋值。 //11.为了与内置版本保持一致,重载前置的递增递减运算符应该返回引用类型。后置的递增递减运算符应该按值返回。后置的递增递减运算符额外接受一个不被使用的int类型的实参(将会被置为0)来区别其前置版本。 //12.很多具有互相作用的运算符的重载,其工作可以交予其具有相关联关系的运算符重载函数完成,比如==的工作可以交予!=来完成等。 //13.箭头运算符永远不能丢掉其成员访问的这个基本含义。可以改变的是箭头从哪个对象当中获取成员,而箭头获取成员这一个事实则永远不变。所以:重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的类的某个对象。
// point->men;根据point的类型不同分别等价于:
// A:(*point).men; point是一个内置的指针类型
// B:point.operator()->men; point是类的一个对象。
class CTest
{
public:
CTest() {str = "szn";}
string* operator ->() {return &str;}
public:
string str;
};
CTest Test;
const char *pStr0 = Test->c_str(); //pStr0 = "szn"
const char *pStr1 = (&Test)->str.c_str(); //pStr1 = "szn" //14.函数调用运算符可以重载为多个版本,相互之间在参数数量或者类型上有所区别。由于类的对象能存储状态,所以比起普通函数来说更加灵活。 //15.function位于头文件functional中,声明在命名空间std中,用于存储一个可调用对象。注意:重载的函数名字不能直接存入function类型的对象中,可以使用函数指针或lambda等来解决这个问题。
int Add(int value0, int value1) {return value0 + value1;}
int Minus(int i, int j) {return i - j;} class CMultiply
{
public:
CMultiply(){}
int operator()(int value0, int value1){return value0 * value1;}
}; CMultiply multiply;
auto divide = [](int i, int j){return j == ? : i / j;};
auto minus = bind(Minus, _2, _1); map<string, function<int (int , int)>> mapFun;
mapFun.insert(make_pair(string("+"), Add));
mapFun.insert(make_pair(string("-"), minus));
mapFun.insert(make_pair(string("*"), multiply));
mapFun.insert(make_pair(string("/"), divide)); int v0 = mapFun["+"](, ); //v0 = 15
int v1 = mapFun["-"](, ); //v1 = -5
int v2 = mapFun["*"](, ); //v2 = 50
int v3 = mapFun["/"](, ); //v3 = 2 //16.通过定义转换构造函数可以将指定类型的对象转换为类类型的对象。通过定义类型转换运算符可以将类类型的对象转换为指定类型的对象。转换构造函数和类型转换运算符共同组成了类类型转换。
// 在实际操作中,很少提供类的类型转换运算符,在大多数情况下,如果类型转换自动发生,用户可能感觉比较意外,而不是感觉受到了帮助。特殊的:对于类来说,定义向bool的类型转换还是比较普遍的。
class CTest
{
public:
CTest() : value(){}
operator int() const {return value;} //不能声明返回类型,形参列表必须为空,通常是const的。
private:
int value;
}; CTest Test;
int value = Test; //value = 0 //17.避免使用二义性的类型转换
// A:当类A定义了一个接受B类对象的转换构造函数,同时B类定义了一个转换目标是A类的类型转换运算符。此时在将B类对象转换为A类对象的时候将产生二义性。
// B:当类定义了多个转换规则,而这些转换涉及的类型本身可以通过其他类型转换联系在一起,此时可能造成二义性(比如类A定义了到int和double的类型转换运算符,而使用一个float类型去接收类型转换构造符的结果时,就会造成二义性)。最典型的情况是算数类型转换。
// C:当我们调用重载的函数的时候,从多个类型转换中进行选择将变得更加复杂,比如:当几个重载函数的参数分别属于不同的类类型,并且这些类类型都定义了同样的转换构造函数,则二义性问题将进一步提升。
class A {A(int){}};
class B {B(int){}}; //即使这里B类的定义为:class B {B(double){}};fun(10);的调用也会有二义性。
void fun(A){};
void fun(B){};
fun(); //调用将出错
// D.如果我们对同一个类型即提供了转换目标是算术类型的类型转换,也提供了重载的运算符,则将遇到重载运算符和内置运算符的二义性问题
class A
{
public:
A(int a) : value(a){}
operator int() {return value;}
friend A operator + (const A &a0, const A &a1) {return a0.value + a1.value;} private:
int value;
};
A a();
int sum = a + ; //二义性冲突
// 基于上述结论得出:除了显示地向bool类型转换之外,我们尽量避免定义类型转换运算符,并尽可能的限制转换构造函数(explicit)。

C++Primer 第十四章的更多相关文章

  1. C++ Primer : : 第十四章 : 重载运算符与类型转换之类型转换运算符和重载匹配

    类型转换运算符 class SmallInt { public: SmallInt(int i = 0) : val(i) { if (i < 0 || i > 255) throw st ...

  2. C++ Primer : 第十四章 : 重载运算与类型转换之重载运算符

    重载前须知 重载运算符是特殊的函数,它们的名字由operator和其后要重载的运算符号共同组成. 因为重载运算符时函数, 因此它包含返回值.参数列表和函数体. 对于重载运算符是成员函数时, 它的第一个 ...

  3. C++ Primer Plus学习:第十四章

    第十四章 C++中的代码重用 包含对象成员的类 将类的对象作为新类的成员.称为has-a关系.使用公有继承的时候,类可以继承接口,可能还有实现(纯虚函数不提供实现,只提供接口).使用包含时,可以获得实 ...

  4. 【C++】《C++ Primer 》第十四章

    第十四章 重载运算与类型转换 一.基本概念 重载运算符是具有特殊名字的函数:由关键字operator和其后要定义的运算符号共同组成.也包含返回类型.参数列表以及函数体. 当一个重载的运算符是成员函数时 ...

  5. C Primer Plus_第四章_字符串和格式化输入输出_编程练习

    Practice 1.输入名字和姓氏,以"名字,姓氏"的格式输出打印. #include int main(void) { char name[20]; char family[2 ...

  6. 《Linux命令行与shell脚本编程大全》 第十四章 学习笔记

    第十四章:呈现数据 理解输入与输出 标准文件描述符 文件描述符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误 1.STDIN 代表标准输入.对于终端界面 ...

  7. perl 第十四章 Perl5的包和模块

    第十四章 Perl5的包和模块 by flamephoenix 一.require函数  1.require函数和子程序库  2.用require指定Perl版本二.包  1.包的定义  2.在包间切 ...

  8. Gradle 1.12 翻译——第十四章. 教程 - 杂七杂八

    有关其它已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或訪问:http://gradledoc.qiniudn.com ...

  9. C和指针 (pointers on C)——第十四章:预处理器

    第十四章 预处理器 我跳过了先进的指针主题的章节. 太多的技巧,太学科不适合今天的我.但我真的读,读懂.假设谁读了私下能够交流一下.有的小技巧还是非常有意思. 预处理器这一章的内容.大家肯定都用过.什 ...

随机推荐

  1. selenium弹窗关闭

    经历了两天的摸索,终于能把弹窗关闭.定位弹窗关闭按钮也尝试了直接用id 定位,class name定位,css_selector定位,连Xpath定位也用上了,但还是关闭不了. 分析其中原因:程序过程 ...

  2. ip sevices

    http://www.ip138.com/ip2city.asp http://www.bliao.com/ip.phtml http://www.whereismyip.com/ http://ww ...

  3. Medusa: Gauges for JavaFX

    Medusa: Gauges for JavaFX https://community.oracle.com/docs/DOC-992746

  4. js判断是否为空火undefined是否给undefined加引号

    js判断是否为空为undefined如果判断的是类型则用typeof(),如果其本身就是“undefind”字符窜,则不能这样判断, 这样typeof之后是字符串类型就判断不出来了,这是需要去掉typ ...

  5. MoSCoW Method

    When managing a project, it is important to develop a clear understanding of the customers' requirem ...

  6. HBASE架构解析(一)

    http://www.blogjava.net/DLevin/archive/2015/08/22/426877.html 前记 公司内部使用的是MapR版本的Hadoop生态系统,因而从MapR的官 ...

  7. AspectJ本质剖析

    AOP一共有两种方式,spring默认使用的是动态代理(JDK自带的动态代理或者使用cglib的动态代理)和静态代理(ASPECTJ) http://blog.csdn.net/zhao9tian/a ...

  8. SET Statements (Transact-SQL)

    The Transact-SQL programming language provides several SET statements that change the current sessio ...

  9. 使用APICloud写“华为商城”(前端+后端) 无保留提供源码

    第一次分享了一个可以算是完整的手机商城项目,之前从别人的源码中得到了许多帮助,现在入门了也希望能帮一下大家. 注: 前端,后端都有 数据用的是APICloud的MCM,所以小心流量. 目前只有Andr ...

  10. ucenter 通信成功后 apps.php无误后 该做的事

    比如你的系统有个登陆功能,在本系统登陆之前要先执行如下代码,先把apps.php里的所有站点先登陆一遍 <meta charset="utf8"> <?php i ...