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中的方法fA::x=10,然后調用Aobj.f(),則Aobj.x=10,然后y=10
d.dispaly()【運行B的方法,因為輸出的時候是從右往左輸出的,所以先調用B中的方法f,此時A::x=11Aobj.x=11y=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!

運行結果:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383811.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383811.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383811.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

strtok函數及其實現

頭文件&#xff1a;#include <string.h> 定義函數&#xff1a;char * strtok(char *s, const char *delim); 函數說明&#xff1a;strtok()用來將字符串分割成一個個片段。參數s 指向欲分割的字符串&#xff0c;參數delim 則為分割字符串&#xff0c;當 strtok()在參數s …

C++小型公司管理系統

項目要求&#xff1a; 編寫一個程序實現小型公司的人員信息管理系統。該公司雇員&#xff08;employee&#xff09;包括經理&#xff08;manager&#xff09;&#xff0c;技術人員&#xff08;technician&#xff09;、銷售員&#xff08;salesman&#xff09;和銷售部經理&…

Linux網絡編程“驚群”問題總結

http://www.cnblogs.com/Anker/p/7071849.html 1、前言 我從事Linux系統下網絡開發將近4年了&#xff0c;經常還是遇到一些問題&#xff0c;只是知其然而不知其所以然&#xff0c;有時候和其他人交流&#xff0c;搞得非常尷尬。如今計算機都是多核了&#xff0c;網絡編程框架也…

【Java學習筆記六】常用數據對象之String

字符串 在Java中系統定義了兩種類型的字符串類&#xff1a;String和StringBuffer String類對象的值和長度都不能改變&#xff0c;稱為常量字符串類&#xff0c;其中每個值稱為常量字符串。 StringBuffer類對象的值和長度都可以改變&#xff0c;稱為變量字符串類&#xff0c;其…

【Java學習筆記七】常用數據對象之數組

同一般的對象創建和定義一樣&#xff0c;數組的定義和創建可以分開進行也可以合并一起進行。 一維數組定義格式&#xff1a; <元素類型>[] <數組名>;//[]也可以放在數組名的后面一維數組創建格式&#xff1a; new <元素類型>[<元素個數>];執行new運…

yfan.qiu linux硬鏈接與軟鏈接

http://www.cnblogs.com/yfanqiu/archive/2012/06/11/2545556.html Linux 系統中有軟鏈接和硬鏈接兩種特殊的“文件”。 軟鏈接可以看作是Windows中的快捷方式&#xff0c;可以讓你快速鏈接到目標檔案或目錄。 硬鏈接則透過文件系統的inode來產生新檔名&#xff0c;而不是產生…

【Java學習筆記八】包裝類和vector

包裝類 在Java語言中&#xff0c;每一種基本的數據類型都有相應的對象類型&#xff0c;稱為他們基本類型的包裝類&#xff08;包裹類&#xff09;。 字節byte&#xff1a;Byte、短整數型short&#xff1a;Short 標準整數型int&#xff1a;Integer、長整數型long&#xff1a;Lo…

Linux C++線程池實例

http://www.cnblogs.com/danxi/p/6636095.html 想做一個多線程服務器測試程序&#xff0c;因此參考了github的一些實例&#xff0c;然后自己動手寫了類似的代碼來加深理解。 目前了解的線程池實現有2種思路&#xff1a; 第一種&#xff1a; 主進程創建一定數量的線程&#xff0…

Java編寫簡單的自定義異常類

除了系統中自己帶的異常&#xff0c;我們也可以自己寫一些簡單的異常類來幫助我們處理問題。 所有的異常命名都是以Exception結尾&#xff0c;并且都是Exception的子類。 假設我們要編寫一個人類的類&#xff0c;為了判斷年齡的輸入是否合法&#xff0c;我們編寫了一個名為Il…

shared_ptr簡介以及常見問題

http://blog.csdn.net/stelalala/article/details/19993425 本文中的shared_ptr以vs2010中的std::tr1::shared_ptr作為研究對象。可能和boost中的有些許差異&#xff0c;特此說明。 基本功能 shared_ptr提供了一個管理內存的簡單有效的方法。shared_ptr能在以下方面給開發提供便…

【Java學習筆記九】多線程

程序&#xff1a;計算機指令的集合&#xff0c;它以文件的形式存儲在磁盤上&#xff0c;是應用程序執行的藍本。 進程&#xff1a;是一個程序在其自身的地址空間中的一次執行活動。進程是資源申請、調度和獨立運行的單位&#xff0c;因此&#xff0c;它使用系統中的運行資源。而…

【C++11新特性】 C++11智能指針之weak_ptr

http://blog.csdn.net/xiejingfa/article/details/50772571 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50772571 如題&#xff0c;我們今天要講的是C11引入的三種智能指針中的最后一個&#xff1a;weak_ptr。在學習weak_ptr之…

【C++學習筆記四】運算符重載

當調用一個重載函數和重載運算符時&#xff0c;編譯器通過把您所使用的參數類型和定義中的參數類型相比較&#xff0c;巨鼎選用最合適的定義。&#xff08;重載決策&#xff09; 重載運算符時帶有特殊名稱的函數&#xff0c;函數名是由關鍵字operator和其后要重載的運算符符號…

【C++11新特性】 C++11智能指針之unique_ptr

原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50759210 在前面一篇文章中&#xff0c;我們了解了C11中引入的智能指針之一shared_ptr&#xff0c;今天&#xff0c;我們來介紹一下另一種智能指針unique_ptr。 unique_ptr介紹 uni…

C++派生類對象和基類對象賦值

在C中&#xff0c;我們允許 將派生類對象賦給基類對象。&#xff08;不允許將基類對象賦給派生類對象&#xff09; 只會將基類對象成員賦值用基類指針指向派生類對象。&#xff08;不允許用派生類指針指向基類對象&#xff09; 基類指針只能操作基類中的成員基類引用作為派生類…

【C++11新特性】 C++11智能指針之shared_ptr

http://blog.csdn.net/Xiejingfa/article/details/50750037 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50750037 C中的智能指針首先出現在“準”標準庫boost中。隨著使用的人越來越多&#xff0c;為了讓開發人員更方便、更安…

C++(純)虛函數重寫時訪問權限更改問題

我們知道在Java中是自動實現多態的&#xff0c;Java中規定重寫的方法的訪問權限不能縮小。那么在C中我們實現多態的時候是否可以更改&#xff08;縮小&#xff09;訪問權限呢&#xff1f; 經過測試&#xff0c;得到的答案如下&#xff1a;如果用基類指針指向派生類對象實現多態…

C++ — 智能指針的簡單實現以及循環引用問題

http://blog.csdn.net/dawn_sf/article/details/70168930 智能指針 ____________________________________________________ 今天我們來看一個高大上的東西&#xff0c;它叫智能指針。 哇這個名字聽起來都智能的不得了&#xff0c;其實等你了解它你一定會有一點失望的。。。。因…

C++(靜態)(常量)數據進行初始化問題以及靜態變量析構

在C11標準以前我們都不可以在類中對數據成員初始化&#xff0c;僅能在構造函數中進行初始化&#xff1a; class A {int a,b; double c; string d;A():a(1),b(2),c(3),d(""){} };在C11標準以后我們可以在類中對非靜態成員進行初始化。實際上的機制是在調用構造函數的…

C++this指針的用法

參考博客&#xff1a;https://www.cnblogs.com/zhengfa-af/p/8082959.html 在 訪問對象的非靜態成員時會隱式傳遞一個參數&#xff0c;即對象本身的指針&#xff0c;這個指針名為this。 例如&#xff1a; class A {int a1;public:A(){}void GetA(int a){cout<<this-&g…