2013-08-01 71 views
1

我有命名为A三个类,B,和C. B,从A继承和C从B.继承(A - >乙 - > C)。正确继承设计

我也有一个名为IBinary的抽象基类。我想让所有的类都实现IBinary接口。当我从IBinary进行A类继承时,我的代码的输出是C::readb。当A类不从IBinary继承时,输出是B:readb

是什么力量让我的三个类别订阅相同接口的正确方法?如果我只有顶级类(A)从接口类继承,那么我需要重构我的代码,以便我没有像上面那样的解决方案问题。

如果我有明确的所有类从接口类继承的话,我将有一个更复杂的类层次结构,并成为更接近其死亡的钻石。


#include <iostream> 

class IBinary { 
public: 
    virtual void readb(std::istream& in) = 0; 
}; 

// Basic A -- change whether this inherits from IBinary 
class A : public IBinary { 
public: 
    A() {}; 

    void readb(std::istream& in) {} 
}; 

// Specialized A 
class B : public A { 
public: 
    B() {}; 

    void load() { 
     this->readb(std::cin);  // <-- which readb is called? 
    } 
    void readb(std::istream& in) { 
     std::cout << "B::readb" << std::endl; 
    } 
}; 

// Specialized B 
class C : public B { 
public: 
    C() {}; 

    void readb(std::istream& in) { 
     std::cout << "C::readb" << std::endl; 
    } 
    void foo() { 
     B::load(); 
    } 
}; 

int main() { 
    C c; 
    c.foo(); 
} 
+0

我不明白这个问题。你想要什么* c.foo'做什么? –

+0

一个类订阅接口是什么意思? – Casey

+0

@Casey我正在使用订阅意味着实现。我想执行更清楚。 – Derek

回答

1

IBinary::readb定义的virtual使所有的差异。

当您从IBinary继承,所有readb S IN的层次,从IBinary覆盖一个隐含虚拟的,太。所以虚拟迪帕克踢,就像它应该。

当你不这样做,那么调用静态解析。由于呼叫在B之内,因此被调用的是B::readb

+0

感谢您的帮助。我正在使用的代码只是没有考虑虚拟调度而设计的。 – Derek

1

只要有从IBinaryA继承,这将让所有的孩子能用作抽象接口IBinary

+0

所以行'this-> readb(std :: cin );'必须成为'this-> B :: readb(std :: cin);'? – Derek

+2

@Derek当你明确表示它应该是虚拟的并且在运行时决定时,为什么要调用'B :: readb'? –

1

你看到这种现象的原因是,在短,因为A::readb未声明virtual

由于IBinary::readbvirtual,当从它A继承,A::readb变得virtual默认。

如果您将virtual添加到readb的每个声明中,而不仅仅是第一个,您的代码将表现得更加一致。由于这个原因,很多C++代码风格指南都要求所有派生类中的所有virtual方法都被声明为virtual,即使它们不是祖先基类。

+0

将虚拟添加到所有'readb's不会有任何区别。将它从'IBinary :: readb'中移除。 – jrok