Effective C++改善程序与设计的55个具体做法 学习笔记(三)

目录

(1)条款08:别让异常逃离析构函数(这条理解的不好,看官可忽略或者帮我理解理解)

(2)条款09:绝不在构造和析构过程中调用virtual函数

(3)条款10:令operator = 返回一个reference to *this。

(4)条款11:在operator=中处理“自我赋值”

(5)条款12:复制对象时勿忘其每一个成分


人生美好,今日之工乃为明日之秀,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:复制对象时勿忘其每一个成分

这条适用于拷贝构造函数或“=”运算符。在写这些函数的时候要确保每一个成员变量都被正确拷贝复制。

注意:不要用一个赋值函数来调用另一个赋值函数,应该将重复代码再起一个函数供这两个函数调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值