1. 程式人生 > >多繼承引起的二義性

多繼承引起的二義性

技術 public com 副本 類結構 進行 常見 .cn 現實

  多重繼承可以反映現實生活中的實際情況,能有有效的處理一些較復雜的問題,使編程具有靈活性。但是多重繼承也引起了一些值得註意的問題,它增加了程序的復雜度,使程序的編寫和維護變得相當困難。其中最常見的問題就是繼承成員同名而產生的二義性(Ambiguous)問題。

①調用不同基類的同名成員時可能出現二義性

 1 class A
 2 {
 3     public:
 4         void setA(int a);
 5         int get();
 6     private:
 7         int a;
 8 } ;
 9 class B
10 {
11     public
: 12 void setB(int b); 13 int get(); 14 private: 15 int b; 16 } ; 17 18 class C:public A,public B 19 { 20 public: 21 void setC(int c); 22 int getC(); 23 private: 24 int c; 25 };

  在執行obj.get();時將是有二義性的。因為類C分別從類A類B繼承了兩個不同版本的get()成員函數,因此,obj.get();到底調用哪個get()版本,編譯器將無從知曉。

對於這種二義性問題,常見有兩種解決方法:

(1)使用作用域分辨符::加以消除。

obj.A::get();

obj.B::get();

(2)在類C中也定義成員函數get()函數,則有類C的對象obj訪問get()函數obj.get()沒有二義性,這是因為當派生類中的成員與基類中的成員重名時,派生類中的同名成員將被調用。

 1 class A
 2 {
 3     public:
 4         void setA(int a);
 5         int get();
 6     private:
 7         int a;
 8 } ;
 9 class B
10 { 11 public: 12 void setB(int b); 13 int get(); 14 private: 15 int b; 16 } ; 17 18 class C:public A,public B 19 { 20 public: 21 void setC(int c); 22 int get(); 23 //此處改為這樣 24 private: 25 int c; 26 };

②訪問共同基類的成員時可能出現二義性

  當一個派生類有多個基類,而這些基類又有一個共同的基類時,也就是所謂的菱形繼承。這時對這個共同基類中成員的訪問可能出現二義性。

 1 class A
 2 {
 3     public:
 4         void disp(); 
 5     private:
 6         int a;
 7 };
 8 
 9 class B1:public A
10 {
11     public:
12         void dispB1();
13     private: 
14         int b1;
15 };
16 class B2:public A
17 {
18     public:
19         void dispB2();
20     private: 
21         int b2;
22 };
23 
24 class C:public B1,public B2
25 {
26     public:
27         void dispC();
28     private: 
29         int c;
30 };

在此類結構下,如果創建類C的對象c1:

C c1;

則下面的兩個訪問都有二義性:

c1.disp();

c1.A::disp();

  這是因為B1,B2分別從類A中繼承了一個disp()成員函數的副本,因此類C中就有了分別從類B1,B2兩條不同路線上繼承過來的disp()版本,盡管這兩個版本的函數完全相同,但是語句“c1.disp();”將使編譯器無從知曉到底調用從類B1繼承來的disp(),還是調用從類B2繼承來的disp(),這就是導致二義性的原因。

語句“c1.A::disp();”產生二義性的道理相同,不過下面的兩條調用語句卻是正確的:

c1.B1::disp();

c1.B2::disp();

因為通過“B1::”及“B2::”的限定,明確告訴編譯器應該調用從哪條路徑上繼承過來的disp()。

  在一個類中保留間接共同基類 的多份同名成員,雖然有時是必要的,可以在不同的數據成員中分別存放不同的數據,也可以通過構造函數分別對它們進行初始化。但在大多數情況下,這種現象是人們不希望出現的。

因為保留多份數據成員的副本,不僅占用較多的存儲空間,還增加了訪問這些成員時的困難。而且在實際上,並不需要有多份副本,為此,c++中提供了虛基類(Virtual Base Class)技術來解決這個問題。

關於虛基類方面的內容請跳轉至http://www.cnblogs.com/tenjl-exv/p/7625836.html

多繼承引起的二義性