c++中多重繼承與虛繼承的實(shí)現(xiàn)
一、多重繼承(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ù)用了Flyable和Swimmable的方法,無(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. 虛繼承解決菱形繼承的示例
修改上面的代碼,給Flyable和Swimmable的繼承加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)鍵變化:
- 數(shù)據(jù)冗余解決:Duck對(duì)象中只有一份age,不再有重復(fù)副本;
- 二義性解決:直接訪問(wèn)duck.age無(wú)編譯錯(cuò)誤,編譯器明確知道訪問(wèn)唯一的age;
- 構(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é)
- 多重繼承:允許一個(gè)類(lèi)繼承多個(gè)基類(lèi),復(fù)用多類(lèi)特性,但會(huì)引發(fā)菱形繼承的數(shù)據(jù)冗余和二義性問(wèn)題;
- 虛繼承:通過(guò)
virtual關(guān)鍵字聲明繼承,將共同基類(lèi)變?yōu)樘摶?lèi),使其在最終派生類(lèi)中僅保留一份實(shí)例,解決菱形繼承的核心問(wèn)題; - 關(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)文章希望大家以后多多支持腳本之家!
- C++多重繼承與虛繼承分析
- C++多繼承(多重繼承)的實(shí)現(xiàn)
- 關(guān)于C++多重繼承下虛表結(jié)構(gòu)的問(wèn)題
- C/C++中多重繼承詳解及其作用介紹
- C++多重繼承及多態(tài)性原理實(shí)例詳解
- C++實(shí)現(xiàn)的多重繼承功能簡(jiǎn)單示例
- 深入解析C++中類(lèi)的多重繼承
- C++ 多重繼承和虛擬繼承對(duì)象模型、效率分析
- 關(guān)于C++中菱形繼承和虛繼承的問(wèn)題總結(jié)
- C++ 繼承,虛繼承(內(nèi)存結(jié)構(gòu))詳解
- C++中虛繼承時(shí)的構(gòu)造函數(shù)示例詳解
相關(guān)文章
C++之動(dòng)態(tài)數(shù)組vector解讀
這篇文章主要介紹了C++之動(dòng)態(tài)數(shù)組vector解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
Opencv 馬賽克和毛玻璃效果與圖片融合的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了通過(guò)OpenCV實(shí)現(xiàn)馬賽克和毛玻璃濾鏡效果與圖片的融合,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
C語(yǔ)言模擬實(shí)現(xiàn)密碼輸入的示例代碼
本文主要介紹了C語(yǔ)言模擬實(shí)現(xiàn)密碼輸入的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
C語(yǔ)言實(shí)現(xiàn)自動(dòng)發(fā)牌程序
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)自動(dòng)發(fā)牌程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
詳解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é),其中重點(diǎn)是對(duì)于數(shù)組的內(nèi)存分配相關(guān)方面的知識(shí)整理,需要的朋友可以參考下2016-04-04
C語(yǔ)言實(shí)現(xiàn)掃雷算法簡(jiǎn)易版
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷算法簡(jiǎn)易版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07

