C++ 多重繼承與虛繼承
在派生類中對基類成員的訪問應該是唯一的。但是,在多繼承情況下,可能造成對基類中某個成員的訪問出現了不一致的情況,這時就稱對基類成員的訪問產生了二義性。
原因之一:
派生類在訪問基類成員函式時,由於基類存在同名的成員函式,導致無法確定訪問的是哪個基類的成員函式,因此出現了二義性錯誤。
例如:
#include<iostream> using namespace std; class Base1 { public: void fun(){cout<<"base1 "<<endl;}; }; class Base2 { public: void fun(){cout<<"base2 "<<endl;}; }; class Derived:public Base1,public Base2{}; int main() { Derived obj; obj.fun(); //產生歧義 return 0; }
編譯時,會提示:
當派生類Derived訪問fun()函式時,無法確定訪問的是Base1的還是Base2的,將出現二義性錯誤。
解決辦法:
1,使用作用域運算子指明訪問的是base1的還是base2的fun函式。
例如:
obj.Base1::fun(); //指明訪問base1的fun函式
2,在類中定義同名成員,使內層函式覆蓋外層的函式。
例如:
class Derived:public Base1, public Base2 { public: voidfun() { cout<<"使用的是內層的fun函式"<<endl; } };
執行:
原因之二
當一個派生類從多個基類派生時,而這些基類又有一個共同的基類,當對這個共同的基類中成員變數進行訪問時,可能出現二義性問題。
例如:
Base為Derived11和Derived12的基類,而Derived2又繼承Derived11和Derived12,當Derived2訪問Base的data時,會出現二義性錯誤,程式碼如下:
class Base { public: int data; }; class Derived11:public Base{}; class Derived12:public Base{}; class Derived2:public Derived11,public Derived12 {}; int main() { Derived2 obj; obj.data=1; //產生二義性 return 0; }
解決方法:
1,作用域運算子
Obj.Derived11::a,指明訪問哪一個基類的data.但是由於派生類的直接基類有一個共同的基類,所以 obj.Base::a是錯誤的。
2,使用虛基類
產生二義性的最主要的原因就是base在派生類Derived2中產生了2個物件,從而導致了對基類Base的成員data訪問的不一致性。要解決這個問題,只需使這個公共基類Base在派生類中只產生一個子物件即可。
雖然在形式上,Derived2繼承Derived11,Derived12,但是在儲存結構上,對data的訪問是指向Base的。