深度探索C++对象模型___小张大肝第五章 11月7号

类的设计者一定要定义纯虚析构函数

  • 因为每一个派生类的析构函数会被编译器加以扩张,以静态调用的方式调用其每一个虚基类以及上一层的基类的析构函数,因此,只要缺乏任何一个基类析构函数的定义,就会导致连接失败。
  • 继承体系中每一个类对象的析构函数会被调用,所以不要把虚析构函数声明为pure。

5.1 无继承情况下的对象构造

  • C++的所有的全局对象都被以初始化的数据来对待

抽象数据类型

  • 显示初始化列表的三项缺点:
    • 只有当类成员都是public ,此法才奏效
    • 只能指定常量,因为它们在编译时期就可以评估求值
    • 由于编译器并没有自动施行之,所以初始化行为的失败可能性会高一些

为继承做准备

  • 虚函数的导入引发的问题
    • 每个类对象多负担一个vptr指针
    • 构造函数被附加一些代码,以便将vptr设定初值
    • 合成一个拷贝构造和拷贝赋值,而且其操作不在是不重要的

5.2 继承体系下的对象构造

编译器扩充构造函数的操作大约如下

  • 记录在成员初始化列表中的数据成员初始化操作会被放进构造函数的函数本体,并以成员的声明顺序为顺序
  • 如果一个成员并没有出现在成员初始化列表之中,但它有一个默认构造函数,那么该默认构造函数必须被调用
  • 在那之前,如果一个类对象有虚表指针,它们必须被设定初值,指向适当的虚表
  • 在那之前,所有上一层的基类构造函数必须被调用,已基类的声明顺序为顺序(与成员初始化列表中的顺序没有关联)
  • 在那之前,所有虚基类的构造函数必须被调用,从左到右,从最深到最浅。

虚拟继承

  • 在一个类的构造函数(和析构函数)中,经由构造中的对象调用一个虚函数,其函数实例应该是在此类中有作用的那个。
  • vptr的初始化操作:在基类构造函数调用操作之后,但是在程序员供应的代码或是成员初始化列表中所列的成员初始化操作之前。
  • vptr必须被设定的两种情况
    • 当一个完整的对象被构造起来时
    • 当一个基类子对象调用了一个虚函数时。

5.3 对象复制语意学

  • 不准将一个类对象指定给另一个类对象,那么只要将拷贝赋值操作声明为私有的,并且不提供其定义即可。

  • 以下情况拷贝赋值操作不会表现出bitwise copy 语意

    • 当类内含一个成员对象,而其类有一个拷贝赋值运算符时
    • 当一个类的基类有一个拷贝复制操作符时
    • 当一个类声明了任何虚函数
    • 当一个类继承一个虚基类时
  • C++ Srandard 并没有规定那些代表虚基类的子对象是否该被隐式定义的拷贝赋值操作符指派内容一次以上。

  • 建议尽可能不要允许一个虚基类的拷贝操作,一个比较奇怪的建议,不要再任何虚基类中声明数据。

5.4 对象的效能

5.5 析构语义学

  • 如果类没有定义析构函数,那么只有在类内含的成员对象(或者是类自己的基类)拥有析构函数的情况下,编译器才会自动合成一个出来。

  • 析构函数扩展的方式类似于构造函数被扩展的方式,但顺序相反

    • 析构函数的函数本体首先被执行
    • 如果类拥有成员类对象,而后者拥有析构函数,那么他们会以其声明顺序的相反顺序被调用
    • 如果对象内含一个vptr,现在被重新设定,指向适当的基类的虚表
    • 如果有任何直接的非虚基类拥有析构函数,它们会以其声明顺序的相反顺序被调用
    • 如果有任何虚基类有析构函数,而目前讨论的类是最尾端的类,那么它们会以其原来的构造顺序的相反顺序被调用
  • 像构造函数一样,析构函数最佳实现策略是维护两份析构函数实例

    • 一个完整类对象实例,总是设定好vptrs,并调用虚基类的析构函数
    • 一个基类子对象的实例:除非在析构函数中调用一个虚函数,否则他绝不会调用虚基类构造函数并设定vptr
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值