轉自:http://www.cnblogs.com/lintong/archive/2012/07/28/2613002.html
1. 什么是多重繼承的二義性
class A{ public: void f(); } class B{ public: void f(); void g(); } class C:public A,public B{ public: void g(); void h(); };
如果聲明:C c1,則c1.f();具有二義性,而c1.g();無二義性(同名覆蓋)。
2. 解決辦法一 -- 類名限定
調用時指名調用的是哪個類的函數,如
c1.A::f(); c1.B::f();
3. 解決辦法二 -- 同名覆蓋
在C中聲明一個同名函數,該函數根據需要內部調用A的f或者是B的f。如
class C:public A,public B{ public: void g(); void h(); void f(){ A::f(); } };
4. 解決辦法三 -- 虛基類(用於有共同基類的場合)
virtual 修飾說明基類,如:
class B1:virtual public B
虛基類主要用來解決多繼承時,可能對同一基類繼承繼承多次從而產生的二義性。為最遠的派生類提供唯一的基類成員,而不重復產生多次拷貝。注意:需要在第一次繼承時就要將共同的基類設計為虛基類。虛基類及其派生類構造函數建立對象時所指定的類稱為最(遠)派生類。
- 虛基類的成員是由派生類的構造函數通過調用虛基類的構造函數進行初始化的。
- 在整個繼承結構中,直接或間接繼承虛基類的所有派生類,都必須在構造函數的成員初始化表中給出對虛基類的構造函數的調用。如果未列出,則表示調用該虛基類的缺省構造函數。
- 在建立對象時,只有最派生類的構造函數調用虛基類的構造函數,該派生類的其他基類對虛基類的構造函數的調用被忽略。
class B{ public: int b; } class B1:virtual public B{ priavte: int b1; } class B2:virutual public B{ private: int b2; } class C:public B1,public B1{ private: float d; } C obj; obj.b;//正確的
如果B1和B2不采用虛繼續,則編譯出錯,提示“request for member 'b' is ambiguous”。這是因為,不指名virtual的繼承,子類將父類的成員都復制到自己的空間中,所以,C中會有兩個b。
#include<iostream> using namespace std; class B0{ public: B0(int n) { nv=n; cout<<"i am B0,my num is"<<nv<<endl; } void fun() { cout<<"Member of Bo"<<endl; } private: int nv; }; class B1:virtual public B0{ public: B1(int x,int y):B0(y){ nv1=x; cout<<"i am B1,my num is "<<nv1<<endl; } private: int nv1; }; class B2:virtual public B0{ public: B2(int x,int y):B0(y){ nv2=x; cout<<"i am B2,my num is "<<nv2<<endl; } private: int nv2; }; class D:public B1,public B2{ public: D(int x,int y,int z,int k):B0(x),B1(y,y),B2(z,y){ nvd=k; cout<<"i am D,my num is "<<nvd<<endl; } private: int nvd; }; int main(){ D d(1,2,3,4); d.fun(); return 0; }
d.fun()的結果是:
i am B0,my num is 1 i am B1,my num is 2 i am B2,my num is 3 i am D,my num is 4 Member of Bo