您好,登錄后才能下訂單哦!
在缺省情況下,C++中的繼承是按值組合的一種特殊情況,比如:
class B :virtual public A{ ... };
每個B類對象都含有其A基類子對象的所有非靜態數據成員,以及在B中聲明的非靜態數據成員。類似地,當派生類自己也作為一個基類對象時,如:
class C :virtual public B{ ... };
則C 類對象含有在C中聲明的所有非靜態數據成員,以及其B子對象的所有非靜態數據成員和A子對象的所有非靜態數據成員。
在單繼承下,這種由繼承支持的.特殊形式的按值組合提供了最有效的,最緊湊的對象表示。在多繼承下,當一個基類在派生層次中出現多次時就會有問題。 最主要的實際例子是
iostream 類層次結構,在下圖 ostream 和 istream 類都從抽象 ios 基類派生而來,而 iostream 類又是從 ostream 和 istream 派生:
class iostream :
public istream , public ostream { ... };
缺省情況下,每個 iostream 類對象含有兩個 ios 子對象:在 istream 子對象中的實例以及在 ostream 子對象中的實例。這為什么不好?從效率上而言,存儲 ios 子對象的兩個復本,浪費了存儲區,因為 iostream 只需要一個實例。而且 ios 構造函數被調用了兩次,每個子對象一次,更嚴重的問題是由于兩個實例引起的二義性,例如:任何未限定修飾地訪問 ios 的成員都將導致編譯時刻錯誤。到底訪問哪個實例?如果 ostream 和 istream 對其 ios 子對象的初始化稍稍不同,會怎樣呢?怎樣通過 iostream 類保證這一對 ios 值的一致性?在缺省的按值組合機制下,真的沒有好辦法可以保證這一點。
C++語言的解決方案是,提供另一種可替代“按引用組合”的繼承機制:虛擬繼承。在虛擬繼承下,只有一個共享的基類子對象被繼承,而無論該基類在派生層次中出現多少次。共享的基類子對象被稱為虛擬基類,在虛擬繼承下,基類子對象的復制及由此而引起的二義性都被消除了。
C++中虛擬繼承的概念
為了解決從不同途徑繼承來的同名的數據成員在內存中有不同的拷貝造成數據不一致問題,將共同基類設置為虛基類。這時從不同的路徑繼承過來的同名數據成員在內存中就只有一個拷貝,同一個函數名也只有一個映射。這樣不僅就解決了二義性問題,也節省了內存,避免了數據不一致的問題。
class 派生類名:virtual 繼承方式 基類名
virtual是關鍵字,聲明該基類為派生類的虛基類。
在多繼承情況下,虛基類關鍵字的作用范圍和繼承方式關鍵字相同,只對緊跟其后的基類起作用。
聲明了虛基類之后,虛基類在進一步派生過程中始終和派生類一起,維護同一個基類子對象的拷貝。
C++虛擬繼承
◇概念:
C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的數據成員在內存中有不同的拷貝造成數據不一致問題,將共同基類設置為虛基類。這時從不同的路徑繼承過來的同名數據成員在內存中就只有一個拷貝,同一個函數名也只有一個映射。
◇解決問題:
解決了二義性問題,也節省了內存,避免了數據不一致的問題。
◇二義性:
#include "stdafx.h"
#include <iostream>
using namespace std;
//Base
class Base
{
public:
Base(){ cout << "Base called..." << endl; }
void print(){ cout << "Base print..." << endl; }
private:
};
//Sub
class Sub //定義一個類 Sub
{
public:
Sub(){ cout << "Sub called..." << endl; }
void print(){ cout << "Sub print..." << endl; }
private:
};
//Child
class Child : public Base, public Sub //定義一個類Child 分別繼承自 Base ,Sub
{
public:
Child(){ cout << "Child called..." << endl; }
private:
};
int main(int argc, char* argv [])
{
Child c;
//不能這樣使用,會產生二意性,VC下error C2385
//c.print();
//只能這樣使用
c. Base::print();
c. Sub::print();
system( "pause");
return 0;
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。