C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析
預備博客:
C++虛繼承中構造函數和析構函數順序問題以及原理
C++派生類含有成員對象構造函數析構函數順序
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; }同時還要注意調用函數的時候順序為從右往左。
解析:首先我們調用D的構造函數,發現D虛繼承了A,直接繼承了C,間接繼承了B,B中含有成員對象Aobj,因此構造函數的調用順序為:
A(9)【首先調用虛基類的構造函數,輸出A constructor...9】
A(9)【接下來調用B的構造函數,因為B含有成員對象Aobj,所以先調用Aobj的構造函數,輸出A constructor...9】
B(7,8,9)【運行B的構造函數,輸出B constructor...9】
C(7,8,9)【運行C的構造函數,輸出C constructor...】
D(7,8,9)【運行D的構造函數,輸出D constructor...】
d.f()【因為d中沒有f方法,因此我們在其基類中找,發現其間接基類B和虛基類A中含有方法f,但是B中的方法優先級更高,因此訪問的是B中的方法,B中的方法f會調用A中的方法f,A::x=10,然后調用Aobj.f(),則Aobj.x=10,然后y=10】
d.dispaly()【運行B的方法,因為輸出的時候是從右往左輸出的,所以先調用B中的方法f,此時A::x=11,Aobj.x=11,y=11,同時函數返回11,然后再調用Aobj.f(),返回12,再調用A::f(),返回12,輸出12 12 11】
~D()【開始析構,調用順序和調用構造函數的順序相反,先是D,然后再調用C的,調用B的,調用Aobj的,調用A的,輸出destructor D....】
~C()【沒有輸出】
~B()【輸出destructor B...】
~A()【輸出destructor A...】
~A()【輸出destructor A...】
運行結果:
程序二如下:
#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; }解析:理解這個程序需要對含有虛基類的構造順序有比較深刻的認識。
類TopLevel直接繼承了Level1,虛繼承了類Level2,然后這兩個類又直接繼承了類Base2,虛繼承了類Base1,因此最后類TopLevel虛繼承了類Base1和類Level2。
由虛基類首先進行構造可知,我們首先運行的是類Base1的構造函數
【輸出class Base1!】
然后運行類Level2的構造函數,發現虛基類Base1已經構造,則構造直接繼承的類Base2
【輸出class Base2!】
【輸出class Level2!】
再依次運行非虛基類,即類Level1的構造函數
【輸出class Base2!】
【輸出class Level1!】
最后運行TopLevel的構造函數
【輸出class TopLevel!】
運行結果:
總結
以上是生活随笔為你收集整理的C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原神奇馈宝箱刷新在什么位置
- 下一篇: LOl 还有两秒正在传送 眼位过期了 传