目录
(1)条款08:别让异常逃离析构函数(这条理解的不好,看官可忽略或者帮我理解理解)
(2)条款09:绝不在构造和析构过程中调用virtual函数
(3)条款10:令operator = 返回一个reference to *this。
人生美好,今日之工乃为明日之秀,666
接上篇文章https://mp.csdn.net/console/editor/html/106558956
(1)条款08:别让异常逃离析构函数(这条理解的不好,看官可忽略或者帮我理解理解)
简单的说就是析构函数出BUG可能会导致程序退出的时候崩溃或者中断。
举个例子,你写了一个程序,每次点击一个按钮就会,创建100个座位的屋子,classA申请10个,classB申请10个空间,点击关闭析构的时候先析构classA,再析构classB,如果classA的析构函数出现异常,就无法进行classB的析构,导致classB析构失败,程序造成内存泄漏。(等等!我程序异常退出了,内存都释放了,所以异常退出这个例子并没有很严重,析构一旦失败程序就会结束,这个可能是平台等相关的,后续有机会讨论)
书中给出的办法,比如我这里想确保数据库已经被关闭,那么就需要再来一个函数close来确保程序关闭数据库。
(2)条款09:绝不在构造和析构过程中调用virtual函数
在构造和析构函数中不要调用虚函数。
在C++继承关系中,父类指针实例化子类对象是会先走父类的构造函数的,走父类的构造函数时如果调用虚函数调用的则是父类的虚函数。与我们想要达成的效果(调用子类的重载虚函数)不同。
如下:
父类
class MyClass
{
public:
MyClass();
virtual void setData();
int b;
};
MyClass::MyClass()
{
setData();
}
void MyClass::setData()
{
b = 10;
}
子类:
class MySon : public MyClass
{
public:
MySon();
virtual void setData() override;
};
MySon::MySon()
{
}
void MySon::setData()
{
b = 10*10;
}
我们调用:
MyClass *p_myClass = new MySon;
printf("%d\n",p_myClass->b);
打印结果为10。
这里可以看到,我们在调用过程中调用的是父类的虚函数实现,而不是子类的虚函数实现。
解决方案:就别在析构函数中写虚函数。或者让子类也走一遍该函数(不好管理)。可以用一个init函数来让用户手动调用想要调用的函数。
(3)条款10:令operator = 返回一个reference to *this。
这个是为了连续赋值功能。
Widget & operator=(const Widget & rhs)
{
...//赋值操作
return *this;//返回自身
}
(4)条款11:在operator=中处理“自我赋值”
这里就是用到swap函数来处理。
先说问题,如果自我赋值了,可能会导致“指针指向一个已经被删除的对象”。
(5)条款12:复制对象时勿忘其每一个成分
这条适用于拷贝构造函数或“=”运算符。在写这些函数的时候要确保每一个成员变量都被正确拷贝复制。
注意:不要用一个赋值函数来调用另一个赋值函数,应该将重复代码再起一个函数供这两个函数调用。