2014-01-08 118 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