C++-----深度探索C++对象模型-第五章-构造、析构、拷贝语意学(二)

1、虽然一个类的析构函数是虚函数,但是其调用操作员静态的决议出来的。

2、构造函数的函数本体必须条件式的测试传进来的参数,然后决定调用或不调用相关的虚基类构造函数。由最底层的派生类进行虚基类的构造函数的调用,这种机制会压制中间层级类中构造函数对虚基类构造函数的调用。(菱形继承,最底层的派生类会调用最上层虚基类的构造函数,而在调用中间两个基类构造时,将参数设置为flase,这样中间两个基类的构造函数不再调用最上层虚基类的构造函数。)

3、在一个类的构造函数中调用一个虚函数,其函数实例应该是在这个类中有作用的那个。

4、如果在构造函数中调用虚函数,那么这个虚函数应该是以静态的方式决议,根本一点的解决办法:在执行一个构造函数时,必须限制一组虚函数的候选名单,这个候选名单由虚函数指针控制。

5、虚函数指针在基类构造函数调用操作之后,但是在程序员供应的代码或是成员列表初始化中成员初始化操作之前。

6、构造函数的执行算法通常如下:

    1)在派生类构造函数中,所有虚基类以及上一层基类的构造函数被调用。

    2)上述完成之后,对象的虚函数指针被初始化,指向相关的虚函数表。

    3)如果有成员列表初始化,在构造函数体内展开,这必须在虚函数指针设定之后才做,以免有一个虚函数被调用。

    4)执行程序员所提供的代码。

7、虚函数指针有两种必须被设定的情况:

    1)当一个完整的对象被构造起来时,如果直接声明一个基类对象,这个基类对象的构造函数必须设定虚函数指针。、

    2)当一个子对象构造函数调用一个虚函数时,不管是直接调用还是间接调用。

8、当涉及一个class时,并以一个类对象指定给另一个类对象时,可以有下面三种选择:

    1)什么都不做,实施默认行为。

    2)提供一个显式的赋值拷贝操作符函数。

    3)显式的拒绝把一个类对象指定给另一个类对象。

    如果要做到第三点,只需要把拷贝赋值操作符声明为private,并且不提供定义即可。但是这样的话一旦一个成员函数或友元函数企图进行一份拷贝,会在链接期间失败,这会被认为是链接器的原因。

9、只有在默认行为所导致的语意不安全或不正确时,我们才需要设计一个拷贝赋值运算符。

10、如果默认的按位拷贝不能满足要求,则需要显式的定义拷贝赋值运算符,也就是说在下面四种情况下必须显式定义拷贝赋值运算符:

    1)类中有一个成员对象,该对象的类有一个拷贝赋值运算符。

    2)当一个类的基类有一个拷贝赋值运算符时。

    3)类中声明了虚函数。

    4)类继承自一个虚类,不管这个基类有没有拷贝赋值运算符。

11、有时默认操作足够了,但是我们还是要定义一个拷贝构造函数,以打开NRV优化(name return value)但是对于拷贝赋值运算符则不需要这样。

12、拷贝赋值运算符比较复杂,很多编译器甚至都不尝试去取得正确的语意,在这里只提出一些建议:1)其在虚拟继承下的行为不佳,需小心设计。2)尽可能不要允许虚基类函数的拷贝操作。3)建议不要在虚基类中声明数据。

13、区分成员初始化和显式初始化列表。

//成员初始化列表
point3d P1(1.02,2.01,3.21);
//显式初始化列表
point3d P2={1.02,2.01,3.21};

14、时间效能:继承体系的复杂度增加都会导致对象的构造和拷贝成本增加。

15、如果类没有定义一个析构函数,那么只有在类内含有成员对象或者类自己的基类有析构函数的情况下,编译器才会自动合成一个来,否则析构函数视为不需要,也不需要被合成更不需要被调用(其实会合成一个无用的析构函数这本书里很多时候说不会合成是指不会合成一个有用的函数)。虚函数的存在并不需要析构函数的参与。

16、即使定义了一个构造函数,也不一定一定需要合成一个析构函数,是否合成析构函数应该取决于是否需要。

17、一个类的生命结束于其析构函数开始执行之时,由于每一个基类的析构函数轮番被调用,所以派生类实际上变成一个完整的对象,随着基类析构函数的调用,类对象的大小逐渐减小,直到最后一个基类的析构函数被调用。(虚函数指针的变化也随着变化)

18、一个由程序员所定义的析构函数的扩展内容:

    1)析构函数的函数本体首先被执行。

    2)如果类中成员对象,而该成员对象有析构函数,那么会以其声明的相反顺序被调用。

    3)如果类成员内含有一个虚函数指针,现在被重新指定,指向适当的基类的虚函数表。

    4)如果有任何直接的上一层非虚基类有析构函数,它们会以声明顺序相反的顺序被调用。

    5)如果有任何虚基类用有析构函数,而目前讨论这个类是最尾端的类,那么它们会以原来的构造顺序的相反顺序被调用。

你可能感兴趣的:(【C++】,【深度探索C++对象模型】)