最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++中多重繼承與虛繼承的實(shí)現(xiàn)

 更新時(shí)間:2026年03月27日 10:15:46   作者:Ralph_Y  
本文介紹了C++中的多重繼承和虛繼承機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、多重繼承(Multiple Inheritance)

1. 基本概念

多重繼承是指一個(gè)派生類(lèi)同時(shí)繼承多個(gè)基類(lèi),允許派生類(lèi)復(fù)用多個(gè)基類(lèi)的屬性和方法,是C++區(qū)別于Java等語(yǔ)言的重要特性之一。

語(yǔ)法格式

class 派生類(lèi)名 : 繼承方式1 基類(lèi)1, 繼承方式2 基類(lèi)2, ... {
    // 派生類(lèi)成員
};
  • 繼承方式:public/protected/private(和單繼承規(guī)則一致);
  • 核心價(jià)值:讓一個(gè)類(lèi)同時(shí)擁有多個(gè)類(lèi)的特性(比如“汽車(chē)”同時(shí)繼承“交通工具”和“機(jī)械產(chǎn)品”)。

2. 簡(jiǎn)單示例(無(wú)沖突的多重繼承)

#include <iostream>
using namespace std;

// 基類(lèi)1:飛行動(dòng)物
class Flyable {
public:
    void fly() {
        cout << "能飛" << endl;
    }
};

// 基類(lèi)2:游泳動(dòng)物
class Swimmable {
public:
    void swim() {
        cout << "能游泳" << endl;
    }
};

// 派生類(lèi):鴨子(同時(shí)繼承飛行動(dòng)物和游泳動(dòng)物)
class Duck : public Flyable, public Swimmable {
public:
    void quack() {
        cout << "嘎嘎叫" << endl;
    }
};

int main() {
    Duck duck;
    duck.fly();   // 繼承自Flyable
    duck.swim();  // 繼承自Swimmable
    duck.quack(); // 自身方法
    return 0;
}

輸出

能飛
能游泳
嘎嘎叫

這個(gè)示例中,Duck同時(shí)復(fù)用了FlyableSwimmable的方法,無(wú)任何沖突,是多重繼承的理想場(chǎng)景。

3. 多重繼承的核心問(wèn)題:菱形繼承(鉆石繼承)

當(dāng)多個(gè)基類(lèi)繼承自同一個(gè)“共同基類(lèi)”,而派生類(lèi)又同時(shí)繼承這些基類(lèi)時(shí),會(huì)形成菱形結(jié)構(gòu),導(dǎo)致兩個(gè)核心問(wèn)題:

  • 數(shù)據(jù)冗余:共同基類(lèi)的成員會(huì)在派生類(lèi)中存在多份副本;
  • 二義性:訪問(wèn)共同基類(lèi)的成員時(shí),編譯器無(wú)法確定訪問(wèn)哪一份副本。

菱形繼承示例(有問(wèn)題)

#include <iostream>
using namespace std;

// 共同基類(lèi):動(dòng)物
class Animal {
public:
    int age; // 共同成員
    Animal(int a) : age(a) {}
};

// 基類(lèi)1:飛行動(dòng)物(繼承Animal)
class Flyable : public Animal {
public:
    Flyable(int a) : Animal(a) {}
    void fly() { cout << "能飛,年齡:" << age << endl; }
};

// 基類(lèi)2:游泳動(dòng)物(繼承Animal)
class Swimmable : public Animal {
public:
    Swimmable(int a) : Animal(a) {}
    void swim() { cout << "能游泳,年齡:" << age << endl; }
};

// 派生類(lèi):鴨子(同時(shí)繼承Flyable和Swimmable)
class Duck : public Flyable, public Swimmable {
public:
    // 問(wèn)題1:構(gòu)造函數(shù)需要初始化兩次Animal(數(shù)據(jù)冗余)
    Duck(int a) : Flyable(a), Swimmable(a) {}
    void quack() { cout << "嘎嘎叫" << endl; }
};

int main() {
    Duck duck(2);
    // 問(wèn)題2:訪問(wèn)age會(huì)觸發(fā)二義性編譯錯(cuò)誤
    // cout << duck.age << endl; // 報(bào)錯(cuò):ambiguous reference to 'age'
    
    // 強(qiáng)行指定作用域可以訪問(wèn),但本質(zhì)是兩份age(數(shù)據(jù)冗余)
    cout << duck.Flyable::age << endl;   // 2
    cout << duck.Swimmable::age << endl; // 2
    return 0;
}

關(guān)鍵問(wèn)題分析

  • Duck對(duì)象中存在兩份age(分別來(lái)自Flyable和Swimmable),即使初始化值相同,也是獨(dú)立的內(nèi)存空間;
  • 直接訪問(wèn)duck.age會(huì)編譯報(bào)錯(cuò),因?yàn)榫幾g器不知道你要訪問(wèn)哪一份age;
  • 這種冗余不僅浪費(fèi)內(nèi)存,還可能導(dǎo)致邏輯錯(cuò)誤(比如修改其中一份,另一份不變)。

二、虛繼承(Virtual Inheritance)

1. 基本概念

虛繼承是C++為解決菱形繼承的二義性和數(shù)據(jù)冗余設(shè)計(jì)的機(jī)制:通過(guò)virtual關(guān)鍵字聲明繼承,讓“共同基類(lèi)”成為虛基類(lèi),此時(shí)無(wú)論派生多少次,共同基類(lèi)在最終派生類(lèi)中只保留一份實(shí)例。

語(yǔ)法格式

class 派生類(lèi)名 : virtual 繼承方式 基類(lèi)名 {
    // 成員
};
  • virtual關(guān)鍵字加在“繼承方式”前;
  • 核心作用:讓共同基類(lèi)的實(shí)例在最終派生類(lèi)中唯一。

2. 虛繼承解決菱形繼承的示例

修改上面的代碼,給FlyableSwimmable的繼承加virtual

#include <iostream>
using namespace std;
// 共同基類(lèi):動(dòng)物
class Animal {
public:
    int age;
    Animal(int a) : age(a) {
        cout << "Animal構(gòu)造:age=" << a << endl;
    }
};
// 虛繼承Animal:飛行動(dòng)物
class Flyable : virtual public Animal {
public:
    // 虛繼承下,這里的構(gòu)造函數(shù)不會(huì)直接初始化Animal(由最終派生類(lèi)統(tǒng)一初始化)
    Flyable(int a) : Animal(a) {}
    void fly() { cout << "能飛,年齡:" << age << endl; }
};
// 虛繼承Animal:游泳動(dòng)物
class Swimmable : virtual public Animal {
public:
    Swimmable(int a) : Animal(a) {}
    void swim() { cout << "能游泳,年齡:" << age << endl; }
};
// 最終派生類(lèi):鴨子
class Duck : public Flyable, public Swimmable {
public:
    // 虛繼承下,最終派生類(lèi)必須直接初始化虛基類(lèi)Animal(唯一入口)
    Duck(int a) : Animal(a), Flyable(a), Swimmable(a) {}
    void quack() { cout << "嘎嘎叫" << endl; }
};
int main() {
    Duck duck(2);
    // 無(wú)二義性:只有一份age
    cout << duck.age << endl; // 輸出2
    duck.fly();  // 能飛,年齡:2
    duck.swim(); // 能游泳,年齡:2
    return 0;
}

輸出

Animal構(gòu)造:age=2
2
能飛,年齡:2
能游泳,年齡:2

關(guān)鍵變化:

  1. 數(shù)據(jù)冗余解決:Duck對(duì)象中只有一份age,不再有重復(fù)副本;
  2. 二義性解決:直接訪問(wèn)duck.age無(wú)編譯錯(cuò)誤,編譯器明確知道訪問(wèn)唯一的age;
  3. 構(gòu)造規(guī)則變化:虛基類(lèi)的構(gòu)造函數(shù)由最終派生類(lèi)統(tǒng)一初始化(即使中間基類(lèi)寫(xiě)了初始化,也會(huì)被忽略),保證虛基類(lèi)只構(gòu)造一次。

3. 虛繼承的底層原理

虛繼承的實(shí)現(xiàn)依賴(lài)編譯器的虛基類(lèi)表(vbtable)

  • 每個(gè)虛繼承的類(lèi)會(huì)存儲(chǔ)一個(gè)指向“虛基類(lèi)表”的指針;
  • 虛基類(lèi)表記錄了當(dāng)前類(lèi)到虛基類(lèi)實(shí)例的偏移量;
  • 通過(guò)這個(gè)表,所有派生類(lèi)都能找到唯一的虛基類(lèi)實(shí)例,避免冗余和二義性。

提示:虛繼承有輕微的性能開(kāi)銷(xiāo)(指針訪問(wèn)+表查詢(xún)),因此僅在需要解決菱形繼承時(shí)使用,不要濫用。

三、總結(jié)

  1. 多重繼承:允許一個(gè)類(lèi)繼承多個(gè)基類(lèi),復(fù)用多類(lèi)特性,但會(huì)引發(fā)菱形繼承的數(shù)據(jù)冗余二義性問(wèn)題;
  2. 虛繼承:通過(guò)virtual關(guān)鍵字聲明繼承,將共同基類(lèi)變?yōu)樘摶?lèi),使其在最終派生類(lèi)中僅保留一份實(shí)例,解決菱形繼承的核心問(wèn)題;
  3. 關(guān)鍵規(guī)則:虛基類(lèi)的構(gòu)造函數(shù)由最終派生類(lèi)統(tǒng)一初始化,中間基類(lèi)對(duì)虛基類(lèi)的初始化會(huì)被編譯器忽略。

補(bǔ)充:多重繼承的其他注意事項(xiàng)

  • 如果多個(gè)基類(lèi)有同名方法,即使不是菱形繼承,訪問(wèn)時(shí)也需要指定作用域(比如duck.Flyable::func());
  • 實(shí)際開(kāi)發(fā)中,應(yīng)盡量避免復(fù)雜的多重繼承(可通過(guò)組合/接口替代),僅在確有必要時(shí)使用;
  • C++11后的std::enable_shared_from_this、Qt的QObject等經(jīng)典場(chǎng)景會(huì)用到虛繼承。

到此這篇關(guān)于c++中多重繼承與虛繼承的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)c++ 多重繼承與虛繼承內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++之動(dòng)態(tài)數(shù)組vector解讀

    C++之動(dòng)態(tài)數(shù)組vector解讀

    這篇文章主要介紹了C++之動(dòng)態(tài)數(shù)組vector解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • Opencv 馬賽克和毛玻璃效果與圖片融合的實(shí)現(xiàn)

    Opencv 馬賽克和毛玻璃效果與圖片融合的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了通過(guò)OpenCV實(shí)現(xiàn)馬賽克和毛玻璃濾鏡效果與圖片的融合,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 解讀C++編程的相關(guān)文件操作

    解讀C++編程的相關(guān)文件操作

    這篇文章主要介紹了解讀C++編程的相關(guān)文件操作,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C語(yǔ)言模擬實(shí)現(xiàn)密碼輸入的示例代碼

    C語(yǔ)言模擬實(shí)現(xiàn)密碼輸入的示例代碼

    本文主要介紹了C語(yǔ)言模擬實(shí)現(xiàn)密碼輸入的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C語(yǔ)言實(shí)現(xiàn)自動(dòng)發(fā)牌程序

    C語(yǔ)言實(shí)現(xiàn)自動(dòng)發(fā)牌程序

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)自動(dòng)發(fā)牌程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C語(yǔ)言從編譯到運(yùn)行過(guò)程詳解

    C語(yǔ)言從編譯到運(yùn)行過(guò)程詳解

    這篇文章主要介紹了C語(yǔ)言從編譯到運(yùn)行的一個(gè)過(guò)程的相關(guān)資料,需要的朋友可以參考下面文章具體的內(nèi)容
    2021-09-09
  • 詳解C語(yǔ)言結(jié)構(gòu)體中的函數(shù)指針

    詳解C語(yǔ)言結(jié)構(gòu)體中的函數(shù)指針

    這篇文章主要介紹了詳解C語(yǔ)言結(jié)構(gòu)體中的函數(shù)指針,文中對(duì)函數(shù)指針的基本概念也有講解,需要的朋友可以參考下
    2016-04-04
  • C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié)

    C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié)

    這篇文章主要介紹了C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié),其中重點(diǎn)是對(duì)于數(shù)組的內(nèi)存分配相關(guān)方面的知識(shí)整理,需要的朋友可以參考下
    2016-04-04
  • C語(yǔ)言實(shí)現(xiàn)掃雷算法簡(jiǎn)易版

    C語(yǔ)言實(shí)現(xiàn)掃雷算法簡(jiǎn)易版

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷算法簡(jiǎn)易版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++運(yùn)算符重載與多繼承及二義性詳解

    C++運(yùn)算符重載與多繼承及二義性詳解

    繼友元知識(shí)過(guò)后,就到了今天的C++運(yùn)算符重載的內(nèi)容了,運(yùn)算符重載是C++里比較重要的內(nèi)容。這篇博文不會(huì)一下子講完各種運(yùn)算符重載,因?yàn)樘嗔肆艘膊缓梦照莆?,所以運(yùn)算符重載我準(zhǔn)備分多次記錄和分享,那么接下來(lái)進(jìn)入正文
    2022-11-11

最新評(píng)論

临安市| 叶城县| 临汾市| 邵武市| 绥宁县| 临邑县| 治县。| 库伦旗| 平利县| 澄江县| 长宁区| 拉孜县| 梅州市| 柯坪县| 高邑县| 宜黄县| 镇原县| 定陶县| 洪洞县| 荣成市| 宜川县| 巴里| 平泉县| 邛崃市| 陇南市| 晋中市| 郯城县| 肇源县| 淳化县| 临夏县| 自贡市| 琼海市| 井冈山市| 哈密市| 息烽县| 绵竹市| 连州市| 九江县| 荆州市| 九台市| 广河县|