2012-02-26 149 views
-1

我有以下類:虛擬繼承和同名成員

class Base 
{ 
public: 
    Base() { x = 3; } 
    int x; 
    virtual void foo() {}; 
}; 

class Med1 : public virtual Base 
{ 
public: 
    int x; 
    Med1() { x = 4; } 
    virtual void foo() {}; 
}; 

class Med2 : public virtual Base 
{ 
public: 
    virtual void goo() {}; 
    virtual void foo() {}; 
}; 

class Der : public Med1, public Med2 
{ 
public: 
    Der() {} 
    virtual void foo() {}; 
    virtual void goo() {}; 
}; 

以下代碼:

Base* d = new Der; 
d->foo(); 
cout << d->x; 

輸出:

3 

這是爲什麼? Med1構造函數在構造函數Base之後調用。我猜這是設置Med1::x,而不是Base::x,但爲什麼Der::xBase::x相同,而不是Med1::x。爲什麼沒有歧義?

回答

1

d是一個指向Base,所以d->x是指明確向Base::x。如果它是指向Der的指針,則只會有不明確之處。

+0

哈!有道理,不知道爲什麼我錯過了。但是我改變了代碼,仍然沒有模棱兩可。如果我有一個指向'Der'的指針,它將打印'4'。猜測'Med1'隱藏'Base :: x'。 – 2012-02-26 22:56:24

-1

變量x是不是虛擬的,所以編譯器必須抓住它的頭並說 - 掛在你的基地。因此,去Base->x

+0

當然,在C++中,數據成員不能是虛擬的。 (我猜downvote是關於事實,這個答案意味着一個變量可能是虛擬的......)問題在於'Med1 :: x'不會覆蓋'Base :: x',因爲只有一個虛擬的**函數**聲明可以覆蓋其他虛函數聲明。 – curiousguy 2012-08-04 16:53:32

0

因爲它是指向Base x的指針將是Base。 構造函數的順序是超類,然後是派生類。所以基類的構造函數首先被調用,然後被調用Der。

+0

答案的第一部分與Mike的相同。我在問題中已經提到的第二部分... – 2012-02-26 23:20:50