日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析

發布時間:2023/11/30 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。