C++对象模型-构造拷贝解析语义学 第五章笔记

读完C++对象模型书后,做一个笔记整理
第一章-关于对象
第二章-构造函数语义学
第三章-Data语义学
第四章-Function语义学
第五章-构造拷贝解析语义学
第六章-执行期语义学
第七章-在对象模型的尖端

  • 纯虚基类中若有成员,则需要提供带参数的构造函数,以便子类调用初始化
    C++纯虚函数可以被静态调用,如Abstract_base::interface() 。
  • 而pure virtual destructor必须定义,编译器会为每一个子类扩展其析构函数,以静态调用的方式调用其每个vritual base class及上一层class的析构。
  • 通常vritual destructor不要声明为pure
  • 如果成员函数在子类中不会被改写,最好不要声明为virtual,不能信赖编译器优化把非必要的虚函数转化为静态调用。

无继承体系下的构造

  • 在Plain Ol’Data时,默认构造,拷贝赋值,析构,拷贝,编译器实际执行时,不是没产生就是没被调用。
  • 成员初始化列表,类对自己的数据成员先进行一次默认构造,后执行构造函数中的赋值调用。使用初始化列表时可以减少一次在构造中赋值的过程,于是有了效率差异。成员初始化列表按照类中声明顺序处理,而非列表中顺序。在成员为常量类型,引用类型,及没有默认构造的类类型时必须使用成员初始化列表来初始化。子类初始化父类私有成员时只能通过成员初始化列表调用父类构造来实现。
  • 在有了虚函数之后构造函数会在成员初始化列表调用前插入初始化vptr的代码,且会合成拷贝构造、拷贝赋值函数,并在其中设置vptr。如果很多函数是返回值类型,则提供一个拷贝构造会触发NRV优化。

继承体系下的构造

  • 构造函数基本按 vitual base class构造,base class构造,设置vptr,按成员初始化列表初始化,及默认构造未在初始化列表中的成员。
  • virtual base class需要在最底层子类调用其构造,以免重复调用。virtual base class subobject偏移量需要在执行期间可存取。 base class 若为多继承下第二或后继则需调整this指针。
  • 在拷贝赋值中需要检查是否为自我拷贝,以免错误重置了自身的数据

vptr初始化

  • 子类中,所有虚基类及上层基类构造都会被调用
  • 随后设置vptr指向相关vtbl
  • 将成员初始化列表在构造函数体内扩展开。必须在vptr设定后进行,以免当中会调用虚函数
  • 最后执行程序员代码

由上可知

  • 在类构造函数的成员初始化列表中调用虚 函数是安全,但由于虚函数可能还用到了未初始化好的成员变量,故不推荐。

对象复制语义

  • 如果类有默认bitwise copy语义,则copy assignment operator和copy constructor都不会被合成。

  • 在以下情况时无bitwise语义 a.成员对象有copy assignment operator b.基类有copy assignment operator c.有虚函数时(不能拷贝vptr) d.继承自虚基类。

  • 尽量不要允许在virtual base class的拷贝操作,最好不要在virtual base class中声明数据

  • 对象若未定义析构,在class内成员对象有析构时,编译器才会合成出一个来。

  • 定义析构应基于需要,而非对于构造的对称。

  • 析构基本按照析构本身,声明相反顺序析构成员对象,重设vptr 指向父类vtbl,声明相反顺序调用基类 析构,(若当前是最底层子类)按构造相反顺序析构虚基类。

下一篇 第六章-执行期语义学

你可能感兴趣的:(C++,c++)