c++中的多繼承帶來的二義性問題
本文**:
出現二義性的原因: 派生類在訪問基類成員函式時,由於基類存在同名的成員函式,導致無法確定訪問的是哪個基類的成員函式,因此出現了二義性錯誤。
什麼是多重繼承的二義性
class a
class b
class c:public a,public b;
如果宣告:c c1,則c1.f();具有二義性,而c1.g();無二義性(同名覆蓋)。
解決辦法一 – 類名限定
呼叫時指名呼叫的是哪個類的函式,如
c1.a::f();
c1.b::f();
解決辦法二 – 同名覆蓋
在c中宣告乙個同名函式,該函式根據需要內部呼叫a的f或者是b的f。如
class c:public a,public b
};
解決辦法三 – 虛基類(用於有共同基類的場合)
virtual 修飾說明基類,如:
class b1:virtual public b
虛基類主要用來解決多繼承時,可能對同一基類繼承繼承多次從而產生的二義性。為最遠的派生類提供唯一的基類成員,而不重複產生多次拷貝。注意:需要在第一次繼承時就要將共同的基類設計為虛基類。虛基類及其派生類建構函式建立物件時所指定的類稱為最(遠)派生類。
虛基類的成員是由派生類的建構函式通過呼叫虛基類的建構函式進行初始化的。
在整個繼承結構中,直接或間接繼承虛基類的所有派生類,都必須在建構函式的成員初始化表中給出對虛基類的建構函式的呼叫。如果未列出,則表示呼叫該虛基類的預設建構函式。
在建立物件時,只有最派生類的構造函式呼叫虛基類的建構函式,該派生類的其他基類對虛基類的建構函式的呼叫被忽略。
class b
class b1:virtual public b
class b2:virutual public b
class c:public b1,public b1
c obj;
obj.b;//正確的
如果b1和b2不採用虛繼續,則編譯出錯,提示「request for member 『b』 is ambiguous」。這是因為,不指名virtual的繼承,子類將父類的成員都複製到自己的空間中,所以,c中會有兩個b。
下面我們來看兩個例子:
#includeusing namespace std;
class b0
}; class base2
};class derived: public base1, public base2
};int main()
下面我們再看乙個使用虛基類解決二義性的問題的例子:
/*虛基類*/
#include using namespace std;
class base0
};class base1: virtual public base0
}; class base2: virtual public base0
};class derived: public base1, public base2
};int main()
/*虛基類及其派生類的建構函式*/
#include using namespace std;
class base0 //建構函式
int var0;
void fun0()
};class base1: virtual public base0//派生類的建構函式向基類建構函式傳參
int var1;
void fun()
}; class base2: virtual public base0
int var2;
void fun()
};class derived: public base1, public base2
int var; //同名資料成員
void fun()
};int main()
C 多繼承中的二義性問題
在c 中,派生類繼承基類,對基類成員的訪問應該是確定的 唯一的,但是常常會有以下情況導致訪問不一致,產生二義性。1.在繼承時,基類之間 或基類與派生類之間發生成員同名時,將出現對成員訪問的不確定性 同名二義性。2.當派生類從多個基類派生,而這些基類又從同乙個基類派生,則在訪問此共同基類中的成員時,將...
C 多層繼承二義性問題
多繼承可以看作是單繼承的擴充套件。所謂多繼承是指派生類具有多個基類,派生類與每個基類之間的關係仍可看作是乙個單繼承。多繼承下派生類的定義格式如下 class 派生類名 繼承方式1 基類名1 繼承方式2 基類名2 其中,繼承方式1 繼承方式2 是三種繼承方式 public private protec...
C 多層繼承二義性問題
多繼承可以看作是單繼承的擴充套件。所謂多繼承是指派生類具有多個基類,派生類與每個基類之間的關係仍可看作是乙個單繼承。多繼承下派生類的定義格式如下 class 派生類名 繼承方式1 基類名1 繼承方式2 基類名2 其中,繼承方式1 繼承方式2 是三種繼承方式 public private protec...