美文网首页
C++对象模型5——对象的构造/析构

C++对象模型5——对象的构造/析构

作者: 漫游之光 | 来源:发表于2018-12-25 09:57 被阅读0次

    对象的构造/析构顺序

    1. 初始化虚基类,按照继承顺序,从左到右,从最深到最浅。
    2. 初始化按照继承顺序初始化父类,如果父类还有父类,则递归的初始化父类的父类。
    3. 初始化虚函数表和虚函数指针。
    4. 按照声明顺序初始化初始化列表中的成员,如果成员不在初始化列表中,则使用默认初始化构造初始化。
    5. 执行用户的初始化代码。

    从初始化顺序中可以看出两点:1、如果用户在自己的初始化代码中使用了memcpy函数,可能破坏虚函数指针,导致程序运行出错。2、如果在父类的构造函数中调用虚函数,只能执行父类的虚函数,而无法调用子类的虚函数,因为这个时候的虚函数指针指向的是父类的虚函数数,子类的虚函数表还没有构造出来。

    #include<iostream>
    using namespace std;
    
    class A1{
    public:
        A1(int val){
            cout << "A1()" << endl;
        }
        ~A1(){
            cout << "~A1()" << endl;
        }
    };
    
    class A2{
    public:
        A2(int val){
            cout << "A2()" << endl;
        }
        
        ~A2(){
            cout << "~A2()" << endl;
        }
    };
    
    class B1 :public A1{
    public:
        B1():A1(0){
            cout << "B1()" << endl;
        }
    
        ~B1(){
            cout << "~B1()" << endl;
        }
    };
    
    class B2 :virtual public A2{
    public:
        B2():A2(0){
            cout << "B2()" << endl;
        }
    
        ~B2(){
            cout << "~B2()" << endl;
        }
    };
    
    class C :public B1, public B2{
    public:
        C():A2(0){
            cout << "C()" << endl;
        }
        ~C(){
            cout << "~C()" << endl;
        }
    };
    
    int main(){
        C *c = new C();
        delete c;
        return 0;
    }
    

    这个代码主要想说明两件事,1、在虚继承中,虚基类的初始化应该由子类初始化,因为可能存在多个父类继承同一个虚基类的情况,虚基类的初始化会有歧义。2、按照顺序初始化初始化父类,但是会优先初始化虚基类。此外,还有一点值得注意,在多继承中,会有this指针调整的发生。

    对象的虚构顺序恰恰和构造顺序相反,这也比较好理解,就像对栈的操作,入栈和出栈的顺序恰好相反。也就是说,析构的顺序为:

    1. 执行用户的代码。
    2. 以和声明顺序相反的顺序调用对象成员的析构函数(如果有的话)。
    3. 重新设置虚函数指针,使其指向子类的虚函数表。
    4. 和声明顺序相反的循序递归调用父类的析构的函数。
    5. 以相反的顺序调用虚基类的析构函数。

    相关文章

      网友评论

          本文标题:C++对象模型5——对象的构造/析构

          本文链接:https://www.haomeiwen.com/subject/gcukkqtx.html