天天看點

<C++學習筆記一>——多繼承

本篇文章來自轉載哦,感覺不錯!

一般說來,在派生類中對基類成員的通路應該是唯一的,但是,由于多繼承情況下,可能造成對基類中某成員的通路出現了不唯一的情況,則稱為對基類成員通路的二義性問題。

 

實際上,在上例已經出現過這一問題,回憶一下上例中,派生類A的兩基類B1和B2中都有一個成員函數print()。如果在派生類中通路print()函數,到底是哪一個基類的呢?于是出現了二義性。但是在上例中解決了這個問題,其辦法是通過作用域運算符::進行了限定。如果不加以限定,則會出現二義性問題。

下面再舉一個簡單的例子,對二義性問題進行深入讨論。例如:

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:C c1;

則對函數f()的通路 c1.f();

便具有二義性:是通路類A中的f(),還是通路類B中的f()呢?

解決的方法可用前面用過的成員名限定法來消除二義性,例如:c1.A::f();

或者 c1.B::f();

但是,最好的解決辦法是在類C中定義一個同名成員f(),類C中的f()再根據需要來決定調用A::f(),還是B::f(),還是兩者皆有,這樣,c1.f()将調用C::f()。

同樣地,類C中成員函數調用f()也會出現二義性問題。例如:viod C::h()

這裡有二義性問題,該函數應修改為:void C::h()

或者 void C::h()

或者 void C::f()

另外,在前例中,類B中有一個成員函數g(),類C中也有一個成員函數g()。這時, c1.g();不存在二義性,它是指C::g(),而不是指B::g()。因為這兩個g()函數,一個出現在基類B,一個出現在派生類C,規定派生類的成員将支配基類中的同名成員。是以,上例中類C中的g()支配類B中的g(),不存在二義性,可選擇支配者的那個名字。

當一個派生類從多個基類派生類,而這些基類又有一個共同的基類,則對該基類中說明的成員進行通路時,也可能會出現二義性。例如:

class A
{
public:
int a;
};
class B1 : public A
{
private:
int b1;
};
class B2 : public A
{
private:
int b2;
};
class C : public B1, public B2
{
public:
int f();
private:
int c;
};
           

已知:C c1;

  下面的兩個通路都有二義性:

  c1.a;

  c1.A::a;

  而下面的兩個通路是正确的:

  c1.B1::a;

  c1.B2::a;

  類C的成員函數f()用如下定義可以消除二義性:

  int C::f()

   {

    retrun B1::a + B2::a;

   }

  由于二義性的原因,一個類不可以從同一個類中直接繼承一次以上,例如:

  class A : public B, public B

 

  這是錯誤的。

本文來源:http://developer.zdnet.com.cn/2007/1030/591018.shtml