C++虛擬繼承

来源:https://www.cnblogs.com/GyForever1004/archive/2018/02/09/8436992.html
-Advertisement-
Play Games

假設我們有類 A 、類 B 和類 Test ,類 Test 具有類 A 和類 B 的全部屬性,並且它們都具有 temp 屬性,現在我們需要在類 Test 中實現對 temp 屬性的設定與讀取,故寫出以下程式: ~~~~ include class Base{ public: int temp; }; ...


假設我們有類 A 、類 B 和類 Test ,類 Test 具有類 A 和類 B 的全部屬性,並且它們都具有 temp 屬性,現在我們需要在類 Test 中實現對 temp 屬性的設定與讀取,故寫出以下程式:

#include <iostream>

class Base{
public:
    int temp;
};

class A : public Base{
};

class B : public Base{
};

class Test : public A, public B{
public:
    void setValue(int val){
        temp = val;
    }

    void print(){
        std::cout << temp << std::endl;
    }

};

int main()
{
    Test T = Test();

    T.setValue(1004);
    T.print();

    return 0;
}

費了好大力氣寫出來的程式,保存後編譯居然掛了 0.0

這是因為多重繼承使基類拷貝了多次,最後子類調用相同屬性的話就會產生二義性的問題。

對於上面的程式我們可以這樣更改使之編譯通過:

class Test : public A, public B{
public:
    void setValue(int val){
        A::temp = val;
    }

    void print(){
        std::cout << B::temp << std::endl;
    }

};

程式輸出為0。

這樣就解決了二義性的問題,但這樣的代碼顯得臃腫,而且相同的屬性被拷貝了多次還會浪費記憶體。

虛擬繼承就可以輕鬆解決上面出現的問題,子類依舊繼承基類,但此時不是記憶體的拷貝,而是指向基類的指針,占用一份指針的記憶體。

虛擬繼承程式如下:

#include <iostream>

class Base{
public:
    int temp;
};

class A : virtual public Base{
};

class B : virtual public Base{
};

class Test : public A, public B{
public:
    void setValue(int val){
        temp = val;
    }

    void print(){
        std::cout << temp << std::endl;
    }

};

int main()
{
    Test T = Test();

    T.setValue(1004);
    T.print();

    return 0;
}

應用虛繼承的方式,既解決了二義性的問題,也解決了資源浪費的問題,美滋滋~

溫馨提示:

虛擬繼承雖好,但是不能貪杯,在開發過程中我們應該避免使用多重繼承,它會使得程式變得更加複雜,故出錯的可能性就更高。

補充虛繼承記憶體占用大小(32位機,from百科):

#include <iostream>  

using namespace std;  
  
/* 大小為4 */
class A
{  
public:  
    int a;  
};  

/* 大小為12,變數a,b共8位元組,虛基類表指針4 */
class B :virtual public A  
{  
public:  
    int b;  
};  

/* 與B一樣12 */
class C :virtual public A  
{  
public:  
    int c;  
};  

/* 24,變數a,b,c,d共16,B的虛基類指針4,C的虛基類指針4 */
class D :public B, public C  
{  
public:  
    int d;  
};  
  
int main()  
{  
    A a;  
    B b;  
    C c;  
    D d;  
    
    cout << sizeof(a) << endl;  
    cout << sizeof(b) << endl;  
    cout << sizeof(c) << endl;  
    cout << sizeof(d) << endl;  

    return 0;  
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #有的時候可能要訪問外國的網站下載資料或工具,這時可能出現各種問題,例如谷歌人機驗證顯示不了、網站打不開等,建議使用一個FQ軟體 下載免費版的就行了,土豪請隨意。下載後直接安裝就行了 http://www.softpedia.com/get/Internet/Servers/Proxy-Server ...
  • 在測試過程中發現 如果方法有echo 等函數輸出到PHP的輸出緩存中 存在 sessionID 不會放到http的請求頭中 下次請求也就拿不到sessionid問題 問題的原因 代碼位置:public/index.php 該方法代用方法 代碼:vendor/symfony/http-foundati ...
  • 由於Laravel session機制完全脫離了PHP自帶的session機制 因此對於php.ini 配置session對Laravel 是不會產生影響 代碼路徑: vendor/laravel/framework/src/Illuminate/Session/Store.php 驗證猜測 魔術方 ...
  • 考慮K階變繫數線性遞推方程: 現給定初值a1,a2, ,ak和n>k,要求編程列印an,an-1, ,ak+1的值 該問題用常規的迭代法非常容易解決,現在要考慮的是用遍歷遞歸調用樹的方法求解。n=7,k=3時,遞歸調用樹為 圖中每一個數字代表對應下標的an 為了求a4,a5,a6,a7需要遍歷該遞歸 ...
  • session使用註意點 工作中使用的是session預設的文件緩存 在使用過發現 session()->put("key","values") 發現 沒有設置成功 最後翻源碼發現是使用文件緩存時候需要使用save() 方法才能持久化到資料庫中 源碼:vendor/laravel/framework ...
  • 上篇博文講Spring的IOC容器時說道,雖然容器功能強大,但容器本身只是個空殼,需要我們主動放入裝配對象,並告訴它對象之間的協作關係,然後容器才能按照我們的指示發揮它的魔力,完成裝配bean的使命。這裡,我們把Spring創建應用對象之間的協作關係的行為成為裝配。Spring提供了很多裝配bean ...
  • 如果不瞭解單源最短路徑問題可以自行百度或參考演算法書籍,這裡只給出一種解法,對問題本身不做詳細介紹 在以下求解單源最短路徑問題的代碼中使用了重要的核心函數Findroad,它是求解該問題的基礎,用它可以找出圖中兩頂點間的所有路徑,Findroad配合篩選路徑的SOperate函數即可找出最短路徑.同時 ...
  • selenium簡介 Selenium也是一個用於Web應用程式測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣。支持的瀏覽器包括IE、Mozilla Firefox、Mozilla Suite等。這個工具的主要功能包括:測試與瀏覽器的相容性——測試你的應用程式看是否能夠 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...