2014-01-08 163 views
3

我有一個在類C中定義的受保護的抽象虛擬方法myMethod()。D類繼承自C並定義了myMethod()。現在E類也繼承自C並且還定義了myMethod()。所以,我有這樣的事情:公共虛擬方法在繼承類中被覆蓋保護

這看起來像這樣

class C 
{ 
protected: 
    virtual void myMethod() = 0; 
} 

class D : public class C 
{ 
protected: 
    void myMethod() {/*Do something*/}; 

    void anotherMethod(); 
} 

class E : public class C 
{ 
protected: 
    void myMethod() {/*Do something else*/}; 
} 

現在,如果在D::anotherMethod()我有一個指針,E類的一個對象,然後我不能叫E::myMethod()。沒有什麼錯在這裏:d和E有不同的層次,因此我不能叫E::myMethod()從D.即下面的代碼無法編譯預計:

void D::anotherMethod() 
{ 
    E* myE = new E(); 

    myE->myMethod(); 
} 

現在,如果我改變C的聲明,並E::myMethod()公衆(而保持在d和E protected)重寫的方法,如在下面的代碼,它編譯:

class C 
{ 
public: 
    virtual void myMethod() = 0; 
} 

class D : public class C 
{ 
protected: 
    void myMethod() {/*Do something*/}; 

    void anotherMethod(); 
} 

class E : public class C 
{ 
protected: 
    void myMethod() {/*Do something else*/}; 
} 

我只改變publicprotected C內,而不是在繼承的類d和E.

有誰知道它爲什麼編譯,它背後的邏輯是什麼?

謝謝!

安託萬。

+2

我想,你的設計很糟糕。爲什麼你需要隱藏一個方法,該方法被你的接口聲明爲公共的?另外如果D是從C派生的,那麼D比C是C以及E是C.爲什麼D應該包含E? – dousin

+0

你好dousin,這是一個層次結構,D是一個分支,E是一個葉子:分支可以包含葉子......至於「糟糕的設計」,你可能是對的,我可能需要重新考慮我的架構與否。但首先我想更多地瞭解我觀察到的意外行爲。 – arennuit

回答

2

我們可以用C接口,因爲它是市民: E接口保護,D不能從E訪問,但可以從基類C

如下:

class C 
{ 
public: 
    virtual void myMethod() = 0; 
}; 

class E : public C 
{ 
protected: 
    void myMethod() {/*Do something else*/}; 
}; 


class D : public C 
{ 
protected: 
    void myMethod() {/*Do something*/}; 

    void anotherMethod(){ 
     //C* myE = new E(); // does compile 
     E* myE = new E(); // doesn't compile 

     myE->myMethod(); 
    } 
}; 
+0

你好Jarod42,不知道這是否是編譯器特定的,但你提到的代碼確實與我的MSVC 2008編譯... – arennuit

+1

它不與gcc和鐺... – Jarod42

+2

所以它應該是msvc的錯誤/擴展,I認爲。 – Jarod42