2013-08-01 121 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