1

Multiple inheritance + virtual function mess과 비슷한 상황이 있습니다. 덜 복잡한 환경에서 코드를 복제하여 혼란 스러움을 보여줍니다.다중 상속 및 중복 함수 호출

어떻게 C가 B1 :: 메서드와 B2 :: 메서드를 실행 (하지만 처리하지 않음)했는지 알고 싶습니다.이 메서드는 차례로 상속 된 메서드를 실행합니다.

내가 제대로 작동하는 것으로 볼 수있는 유일한 방법은 부모 클래스가 하위 클래스에 함수 호출을 전파하는 것이므로 C가 아닌 Bx의 vtable에 직접 액세스하기 때문입니다.

두 경우 모두 안전하거나 정의되지 않은 동작, 어떤 함정 등이 있습니까? 그리고 아마도 이것을하는 더 좋은 방법 일 것입니다.

#include <iostream> 
#include <vector> 

class A { 
    static std::vector<A*> listeners; 
public: 
    static void propagate(); 
protected: 
    A() { 
     listeners.push_back(this); 
    } 
    ~A() { 
     for (std::vector<A*>::iterator it = listeners.begin(); it != listeners.end(); ++it) { 
      if (*it == this) { 
       listeners.erase(it); 
       break; 
      } 
     } 
    } 
    virtual void method()=0; 
}; 

std::vector<A*> A::listeners; 

void A::propagate() { 
    for (unsigned int i=0; i < listeners.size(); ++i) { 
     listeners[i]->method(); 
    } 
} 

class B1 : public A { 
protected: 
    B1() {} 
    ~B1() {} 
    void method() { 
     B1inhmethod(); 
    } 
    virtual void B1inhmethod() {} 
}; 
class B2 : public A { 
protected: 
    B2() {} 
    ~B2() {} 
    void method() { 
     B2inhmethod(); 
    } 
    virtual void B2inhmethod() {} 
}; 

class C : public B1, public B2 { 
public: 
    C() {} 
    ~C() {} 
    void B1inhmethod() { 
     std::cout << "\nB1method in C"; 
    } 
    void B2inhmethod() { 
     std::cout << "\nB2method in C"; 
    } 
}; 

int main() { 
    C myclass; 
    A::propagate(); 
    return 0; 
} 

출력 :

B1inhmethod in C 
B2inhmethod in C 
+0

위의 코드는 출력을 생성하지 않습니다. –

+0

코드를 수정했는데 함수 이름에 오타가있었습니다 – dcousens

답변

2

I이 이유는 C는 두개의 사본에서 B1 및 B2 중 하나에서 하나의 상속 있다는 것을 생각한다. 상속 다이어그램은 다음과 같습니다 : 당신은 C를 만들 때

A  A 
|  | 
B1  B2 
    \ /
    \/
    C 

, 그것은 반복적으로 자신의 기본 클래스를 초기화 모두의 B1과 B2의 기본 클래스를 모두 초기화합니다. 이로 인해 A의 마스터 목록에 두 개의 다른 포인터가 추가됩니다. C의 B1 기본 객체에 대한 포인터와 A의 B2 기본 객체에 대한 포인터입니다.이 두 객체는 ​​모두 같은 객체, 즉 C 인스턴스의 일부입니다. 논리적으로 두 개 기본 개체가 포함되어 있으면 두 개의 포인터를 얻을 수 있습니다. 그런 다음 A 객체 목록을 반복하면 C의 B1 구성 요소와 C의 B2 구성 요소가 나올 것이므로 두 메시지가 모두 인쇄됩니다.

원하지 않는 경우 virtual inheritance을 조사하면 B1 및 B2 개체가 모두 A 기본 개체를 공유하게됩니다. 이렇게하면 개체의 사본 하나만 마스터 목록에 추가됩니다. 물론, 모호함을 피하기 위해 C가 method의 구현을 갖기를 원할 것이기 때문에 당신이 이것을한다면 조심해야한다. 정의하지 않으면 두 개의 method 구현이 있으며 어느 부분도 분명히 적합한 호출이 아닙니다.

+0

이 설정은 원했던대로 답변에 감사드립니다. 그리고 링크 : – dcousens

0

나는

void B1inhmethod() { 
    std::cout << "\nB1inhmethod in C"; 
} 
void B2inhmethod() { 
    std::cout << "\nB2inhmethod in C"; 
} 

은 그냥 오타 있다는 B1method()B2method()의 사실 오버라이드에 있고 가정. 그리고 저는 여러분의 질문이이 두 가지가 모두 호출되는 이유라고 가정합니다.

클래스 C는 B1과 B2 모두에서 상속되므로 생성자가 모두 호출되고 둘 다 리스너의 벡터에 추가됩니다.

그런 다음 클래스 메소드 method을 호출해야하는 모호성이 없으므로 B1과 B2는 A를 상속 받고 간단한 다형성을 사용합니다. B1Method와 B2Method가 모두 호출됩니다.

+0

좋은 가정, 오타에 내 나쁜. 귀하의 답변을 주셔서 감사합니다, 난 그냥이 일을 할 수있는 괜찮은 건지, 숨겨진 잡기 등을 확인하고 싶었어요. – dcousens