C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析
預備博客:
C++虛繼承中構(gòu)造函數(shù)和析構(gòu)函數(shù)順序問題以及原理
C++派生類含有成員對象構(gòu)造函數(shù)析構(gòu)函數(shù)順序
C++虛基類成員可見性
程序一如下:
#include<iostream> using namespace std; class A { public:A(int a) :x(a) { cout << "A constructor..." << x << endl; }int f() { return ++x; }~A() { cout << "destructor A..." << endl; } private:int x; }; class B :public virtual A { private:int y;A Aobj; public:B(int a, int b, int c) :A(a), y(c), Aobj(c) { cout << "B constructor..." << y << endl; }int f() {A::f();Aobj.f();return ++y;}void display() { cout << A::f() << "\t" << Aobj.f() << "\t" << f() << endl; }~B() { cout << "destructor B..." << endl; } }; class C :public B { public:C(int a, int b, int c) :B(a, b, c), A(0) { cout << "C constructor..." << endl; } }; class D :public C, public virtual A { public:D(int a, int b, int c) :C(a, b, c), A(c) { cout << "D constructor..." << endl; }~D() { cout << "destructor D...." << endl; } }; int main() {D d(7, 8, 9);d.f();d.display();return 0; }同時還要注意調(diào)用函數(shù)的時候順序為從右往左。
解析:首先我們調(diào)用D的構(gòu)造函數(shù),發(fā)現(xiàn)D虛繼承了A,直接繼承了C,間接繼承了B,B中含有成員對象Aobj,因此構(gòu)造函數(shù)的調(diào)用順序為:
A(9)【首先調(diào)用虛基類的構(gòu)造函數(shù),輸出A constructor...9】
A(9)【接下來調(diào)用B的構(gòu)造函數(shù),因為B含有成員對象Aobj,所以先調(diào)用Aobj的構(gòu)造函數(shù),輸出A constructor...9】
B(7,8,9)【運行B的構(gòu)造函數(shù),輸出B constructor...9】
C(7,8,9)【運行C的構(gòu)造函數(shù),輸出C constructor...】
D(7,8,9)【運行D的構(gòu)造函數(shù),輸出D constructor...】
d.f()【因為d中沒有f方法,因此我們在其基類中找,發(fā)現(xiàn)其間接基類B和虛基類A中含有方法f,但是B中的方法優(yōu)先級更高,因此訪問的是B中的方法,B中的方法f會調(diào)用A中的方法f,A::x=10,然后調(diào)用Aobj.f(),則Aobj.x=10,然后y=10】
d.dispaly()【運行B的方法,因為輸出的時候是從右往左輸出的,所以先調(diào)用B中的方法f,此時A::x=11,Aobj.x=11,y=11,同時函數(shù)返回11,然后再調(diào)用Aobj.f(),返回12,再調(diào)用A::f(),返回12,輸出12 12 11】
~D()【開始析構(gòu),調(diào)用順序和調(diào)用構(gòu)造函數(shù)的順序相反,先是D,然后再調(diào)用C的,調(diào)用B的,調(diào)用Aobj的,調(diào)用A的,輸出destructor D....】
~C()【沒有輸出】
~B()【輸出destructor B...】
~A()【輸出destructor A...】
~A()【輸出destructor A...】
運行結(jié)果:
程序二如下:
#include <iostream> using namespace std; class Base1 { public:Base1(){cout << "class Base1!" << endl;} }; class Base2 { public:Base2(){cout << "class Base2!" << endl;} }; class Level1 :public Base2, virtual public Base1 { public:Level1(){cout << "class Level1!" << endl;} }; class Level2 : public Base2, virtual public Base1 { public:Level2(){cout << "class Level2!" << endl;} }; class TopLevel :public Level1, virtual public Level2 { public:TopLevel(){cout << "class TopLevel!" << endl;} }; int main() {TopLevel obj;return 0; }解析:理解這個程序需要對含有虛基類的構(gòu)造順序有比較深刻的認識。
類TopLevel直接繼承了Level1,虛繼承了類Level2,然后這兩個類又直接繼承了類Base2,虛繼承了類Base1,因此最后類TopLevel虛繼承了類Base1和類Level2。
由虛基類首先進行構(gòu)造可知,我們首先運行的是類Base1的構(gòu)造函數(shù)
【輸出class Base1!】
然后運行類Level2的構(gòu)造函數(shù),發(fā)現(xiàn)虛基類Base1已經(jīng)構(gòu)造,則構(gòu)造直接繼承的類Base2
【輸出class Base2!】
【輸出class Level2!】
再依次運行非虛基類,即類Level1的構(gòu)造函數(shù)
【輸出class Base2!】
【輸出class Level1!】
最后運行TopLevel的構(gòu)造函數(shù)
【輸出class TopLevel!】
運行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原神奇馈宝箱刷新在什么位置
- 下一篇: C++小型公司管理系统