2009-08-07 4 views
4

그래서이 아이디어가 있고 기본적으로 C++로 구현하는 것은 불가능하다고 생각하지만 ... 물어보고 싶습니다. 저는 Stroustrup의 15 장을 읽었고 제 응답을 얻지 못했습니다. 상속 다이아몬드에 대한 10 억 개의 다른 질문이이 질문에 대답하지 않는다고 생각합니다. 그래서 여기에서 묻고 있습니다.비대칭 가상 상속 다이아몬드 in C++

일반적인 기본 클래스를 공유하는 두 기본 클래스에서 상속을 받지만 두 클래스 중 하나만 가상적으로 상속 할 때 어떤 일이 발생합니까? 예를 들어 :

내가 전체 라이브러리를 재 컴파일 할 필요없이 기존 라이브러리를 확장하는 것을 시도하고 있기 때문에 내가 이렇게 할 생각 이유는
class CommonBase { ... }; 

class BaseA : CommonBase { ... }; 

class BaseB : virtual CommonBase { ... }; 

class Derived : BaseA, BaseB { ... }; 

는 (벌레의 깡통을 열고 싶지 않다). 이미 수정하려는 상속 체인이 있습니다. 기본적으로 이런 식으로 (아스키 미술을 변명하십시오)

LibBase 
     | \ 
     | \ 
     | MyBase 
     |  | 
     |  | 
LibDerived | 
     | \ | 
     | \ | 
     | MyDerived 
     |  | 
LibDerived2 | 
     | \ | 
     | \ | 
     | MyDerived2 
     |  | 
LibDerived3 | 
     | \ | 
     | \ | 
     | MyDerived3 
     |  | 
LibConcrete | 
      \ | 
      MyConcrete 

사진을 찍으시겠습니까? "My"클래스의 각 객체를 이 되려면 클래스의 객체가 본질적으로 바뀌지만 상속 다이어그램의 다음 클래스는 기본 클래스 인 "My"의 오버라이드 된 메소드 구현을 사용하고 싶습니다. 도서관 수업의 다른 방법들. 그것은이

class LibDerived : LibBase 

처럼 그래서 라이브러리 클래스가 실질적으로 상속하지 않습니다하지만 할 경우 내 수업이 거의

class MyBase : virtual LibBase {}; 
class MyDerived: virtual MyBase, virtual LibDerived {}; 

MyDerived 이후 상속합니다 vtable에있을 것이다, 그리고 MyBase는 vtable에있을 것이다,이있을 것 단 하나의 LibBase 개체입니까?

나는이 질문이 충분히 희망적이기를 바랍니다.

+2

왜이 기능을 원하십니까?: p – jalf

+0

앞에서 말했듯이, 라이브러리의 클래스의 멤버 함수를 오버라이드하는 클래스를 생성하여 라이브러리의 기능을 확장하려고하지만 해당 클래스에서 상속받은 객체는 여전히 라이브러리에서 사용할 수 있습니다 . 확장하고자하는 구체적인 클래스는 구현을 변경하려는 기본 클래스에서 4 단계의 상속입니다. 다른 파생 된 클래스에서도 해당 기능을 재사용해야하는 곳을 알 수 있으므로 구체적인 클래스에서 필요한 메서드를 재정의하는 것만으로는 충분하지 않습니다. – cheshirekow

답변

2

대답을 간단히하기 위해 가상/비 가상을 복제 된 콘텐츠 또는 복제되지 않은 콘텐츠로 생각합시다.

class LibDerived : LibBase 

선언 : 나는 LibBase 두 번 (이상) LibDerived

class MyBase : virtual LibBase {}; 

의 하강에 입력 할 수 있도록 선언 : 나는 컴파일러는 하나 하나에 MyBase의 descendings에서 LibBase의 두 항목을 최적화 할 수 있습니다.

이 두 선언이 각각 충족되면 우선 순위가 높아져 MyDerived가 LibBase를 2 회 임 플리 멘팅합니다. 하지만 C++의 힘으로 해결할 수 있습니다! MyDerived 가상 함수를 재정의하여 사용할 항목을 선택하십시오. 다른 방법으로 - LibDerived, MyBase, ... 등의 인스턴스를 집계하는 인터페이스 LibBase에서 파생 된 MyDerived 범용 래퍼를 만들고 집계에서 예상 메서드를 호출합니다.

+0

언급 한 해결책을 더 설명 할 수 있습니까? MyDerived 가상 함수에서 내가 원하는 것을 선택하도록 재정의 (override)한다고 할 때, 단지 "두 개의 LibBase 객체가 있다는 사실을 받아들이고 그 중 하나만 노출시키는 메소드를 오버라이드하는"것을 의미합니까? 불행히도 유니버설 래퍼는 내가 원하는 것을 할 것이라고 생각하지 않는다. 왜냐하면 그것이 라이브러리의 나머지 부분과 호환되지 않기 때문이다. 파생 클래스 객체 각각을 라이브러리의 원시 객체처럼 "표시"하고 싶지만 일부 메소드에 대해서는 단순히 다른 구현을 사용하고 싶습니다. – cheshirekow

+1

heritance의'virtual'은 컴파일러가 기본 클래스를 최적화 할 수 있도록 허용하지 않습니다. '가상'기본 클래스는 파생 된 클래스 객체의 상속 트리에서 그 유형이 가상 기본 클래스로 나타나는 횟수에 관계없이 하나의 기본 클래스 하위 객체 만 있다는 것을 보장하기위한 것입니다. 비 가상 기본 클래스는 새로운 기본 클래스 하위 객체를 추가하도록 보장됩니다. 우선 순위가없고 동일한 유형의 두 번째 가상 기반을 추가 할 수있는 옵션이 없습니다. –

+0

Cheshirekow, 답장을 보내 드리겠습니다. 집계 정확히 여러 구현 중에서 선택할 수 있습니다. 단지 주위에 래퍼를 만듭니다. 예를 들어 생성자 시간에 MyConcrete는 예상 구현에 대한 포인터를 받아들이고 aggreate에 대한 각 호출을 delagating하여 노출합니다. "두 개의 LibBase가 있다는 사실을 받아들입니다."- 불행히도 "예"비 가상 선언은 두 개의 복사본 중 어느 멤버를 호출해야하는지 결정하기 위해 각 가상 함수를 수동으로 재정의해야합니다. – Dewfy

2

본질적으로, 당신 말이 맞습니다. 이런 종류의 상속 트리를 사용하려면 LibDerivedLibBase에서 실제로 파생해야합니다.

이 항목이없는 경우 에 가상이 아닌 LibBase이 있고 MyBase에 별개의 가상 LibBase이있는 것을 방지 할 수 없습니다.

+0

계층의 모든 비 가상 상속 링크는 새로운 기본 객체를 도입 할 것이고 모든 가상 상속 링크는 하나의 다른 기본 객체로 압축 될 것입니까? – cheshirekow

+2

정확히. _all_에 대한 하나의 가상 기본 클래스 인스턴스가 있습니다. 기본 클래스가 계층 구조의 가상 기본 클래스로 표시되는 경우 * 클래스에 하나의 기본 클래스 인스턴스가 _있는 경우 각 클래스는 계층에 가상이 아닌 기본 클래스로 나타납니다. –

관련 문제