2013-08-01 2 views
1

A, B 및 C라는 세 클래스가 있습니다. B는 A에서 상속 받고 C는 B에서 상속받습니다 (A -> B -> C).적절한 상속 디자인

또한 IBinary라는 추상 기본 클래스가 있습니다. 모든 클래스가 IBinary 인터페이스를 구현하도록하고 싶습니다. 클래스 A가 IBinary에서 상속 받도록 만들면 코드 출력은 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

virtual의 정의는 IBinary::readb입니다.

IBinary에서 상속 받으면 IBinary의 계층을 오버라이드하는 계층의 모든 readb이 암시 적으로 가상이기도합니다. 그래서 virtual dispatchh가 시작됩니다.

전화를 걸지 않으면 통화가 정적으로 해결됩니다. 전화가 B 안에 있으므로 전화가 걸리는 전화는 B::readb입니다.

+0

도움 주셔서 감사합니다. 나는 가상 디스패치를 ​​염두에두고 설계되지 않은 코드를 사용하려고한다. – Derek

1

그냥 모든 아이들이 추상적 인 인터페이스 IBinary으로서 사용할 수있을 것 IBinary에서 A 상속 있습니다.

+0

그래서'this-> readb (std :: cin);''this-> B :: readb (std :: cin);'가되어야 할 것이다. – Derek

+2

@Derek 왜 명시 적으로 그것이 가상이어야하고 런타임에 결정되어야한다고 말했을 때'B :: readb'를 호출하기를 원합니까? –

1

A::readbvirtual으로 선언되지 않았기 때문에이 동작이 나타나는 이유는 간단합니다.

IBinary::readbvirtual이기 때문에, 그것에서 A 상속이 A::readb는 기본적으로 virtual됩니다.

virtual을 첫 번째 코드가 아닌 readb의 모든 선언에 추가하면 코드가보다 일관성있게 작동합니다. 이러한 이유 때문에 C++에 대한 많은 코드 스타일 지침에서는 virtual 메서드가 모두 조상 기본 클래스가 아니더라도 모든 파생 클래스에서 virtual 메서드를 선언해야한다는 요구 사항을 만듭니다.

+0

모든'readb '에 가상을 추가해도 아무런 차이가 없습니다. 'IBinary :: readb'에서 제거하면됩니다. – jrok