《Effective C++》读书笔记二

xiaoxiao2022-07-05  19

19、避免返回handles(指针,引用,迭代器)指向对象内部成分

即使函数前面加上const,变成

const Point& upperLeft() const{}

意味着调用者拿到Point引用但是不能涂写,但是让调用者拿到了引用,通过拿到的引用对象调用里面的成员,如果执行这句话时该引用已经不存在(销毁),那么会变成一个空悬、虚吊的对象

20、了解inlining的里里外外

21、前置声明和include的区别

一般原则:

头文件中尽量少使用 include,如果可以前置声明解决,那是最好的。实现头文件中也要尽量少 include ,不要 include 没有用到的头文件。

这样做的好处:

     减少编译速度

什么情况用前置声明:

如果类作为指针或引用方式的调用

什么情况必须include:

如果类作为对象调用,或作为静态成员调用

总结一下,对于C++类而言,如果它的头文件变了,那么所有这个类的对象所在的文件都要重新编译,但如果它的实现文件(cpp文件)变了,而头文件没有变(对外的接口不变),那么所有这个类的对象所在的文件都不会因之而重编。因此,避免大量依赖性编译的解决方案就是:在头文件中用class声明外来类(前置声明),用指针或引用代替变量的声明;在cpp文件中包含外来类的头文件。

另外,书上也提倡把class x; class xx; class xxx;的声明放至一个名为”xxxfwd.h”的头文件里,比如”datefwd.h”,这个头文件里面只有声明式,而没有具体的类细节。也就是说,对于某个类,比如MyDate,应该分出三个文件,一个是datefwd.h,里面是一些用到的外来的class声明式;一个是MyDate.h里面是MyDate类的结构声明;一个是MyDate.cpp,它与MyDate.h配对,给出具体的实现细节。

书上说的Handler classes更想让我们在类A的基础上另造一个中间类AImp(成员函数完全与类A一致),这个中间类的成员中里面放置了所有类A需要的外来类的对象,然后类的逻辑细节完全在Almp.cpp中实现,而在A.cpp里面只是去调用Almp.cpp的同名方法。A.h的成员变量只有Almp的指针,这看上去好像一个Handler,因此而得名。

 

22、虚函数

DerivedClass d; BaseClass* bp = &d; DerivedClass* dp = &d; bp->NonVirtualFunction(); // 输出BaseClass的函数 dp->NonVirtualFunction(); // 输出DerivedClass的函数

原因是在于BaseClass:NonVirutalFunction与DerivedClass:NonVirtualFunction都是静态绑定,所以调用的non-virtual函数都是各自定义的版本。

再看下个例子,这是动态绑定

Shape *sr = new Rectangle(); Shape *st = new Triangle(); sr->DrawShape(); //输出Rectangle的函数 st->DrawShape(); //输出Triangle的函数

 

转载请注明原文地址: https://www.6miu.com/read-4968454.html

最新回复(0)