다중 상속을 사용할 때 어떻게 죽음의 다이아몬드를 피할 수 있나요?

StackOverflow https://stackoverflow.com/questions/137282

  •  02-07-2019
  •  | 
  •  

문제

http://en.wikipedia.org/wiki/Diamond_problem

그게 무슨 뜻인지는 알지만, 이를 방지하려면 어떤 조치를 취해야 합니까?

도움이 되었습니까?

해결책

실용적인 예 :

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

클래스 D가 B & C에서 모두 상속되는 방법에 주목하십시오. 그러나 B & C는 모두 A에서 상속됩니다. 이로 인해 클래스 A의 2 부가 vtable에 포함됩니다.

이를 해결하려면 가상 상속이 필요합니다. 사실상 상속되어야하는 클래스 A입니다. 따라서 문제가 해결됩니다.

class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

다른 팁

가상 상속. 그것이 바로 거기에있는 것입니다.

인터페이스의 여러 상속을 사용하는 것을 고수했습니다. 수업의 여러 상속은 때때로 매력적이지만, 정기적으로 의존하면 혼란스럽고 고통 스러울 수도 있습니다.

상속은 강력하고 강력한 무기입니다.정말 필요할 때만 사용하세요.과거에 다이아몬드 상속은 사용자가 "직원"이지만 "위젯 리스너"이기도 하지만 ...

이러한 경우 다중 상속 문제가 발생하기 쉽습니다.

나는 구성과 소유자에 대한 포인터를 사용하여 문제를 해결했습니다.

전에:

class Employee : public WidgetListener, public LectureAttendee
{
public:
     Employee(int x, int y)
         WidgetListener(x), LectureAttendee(y)
     {}
};

후에:

class Employee
{
public:
     Employee(int x, int y)
         : listener(this, x), attendee(this, y)
     {}

     WidgetListener listener;
     LectureAttendee attendee;
};

예, 액세스 권한은 다르지만 코드를 복제하지 않고 이러한 접근 방식을 사용할 수 있다면 덜 강력하기 때문에 더 좋습니다.(대안이 없을 때를 대비해 전력을 절약할 수 있습니다.)

class A {}; 
class B : public A {}; 
class C : public A {}; 
class D : public B, public C {};

이에서 클래스 A의 속성은 클래스 D에서 두 번 반복되어 메모리 사용을 더 많이 사용합니다. 따라서 메모리를 저장하기 위해 VTABLE에 저장되는 클래스 A의 모든 상속 된 속성에 대한 가상 속성을 만듭니다.

글쎄, 끔찍한 다이아몬드의 가장 큰 장점은 그것이 일어날 때 오류라는 것입니다. 피하는 가장 좋은 방법은 상속 구조를 미리 파악하는 것입니다. 예를 들어, 내가 작업하는 하나의 프로젝트에는 시청자와 편집자가 있습니다. 편집자는 시청자의 논리적 서브 클래스이지만 모든 시청자가 서브 클래스 (TextViewer, ImageViewer 등)이므로 편집기는 시청자에서 파생되지 않으므로 최종 문자형 인 ImageEditor 클래스가 다이아몬드를 피할 수 있습니다.

가상 상속을 사용하여 다이아몬드를 피할 수없는 경우. 그러나 가상베이스와 함께 가장 큰 경고는 가상 기반의 생성자가 ~ 해야 하다 가장 파생 된 클래스에 의해 호출되는데, 이는 사실상 파생 된 클래스가 생성자 매개 변수를 제어 할 수 없음을 의미합니다. 또한, 가상 기반의 존재는 체인을 통한 캐스팅에 대한 성능/공간 페널티가 발생하는 경향이 있지만, 첫 번째를 넘어서 더 많은 페널티가 있다고 생각하지는 않습니다.

또한 사용하려는베이스에 대해 명백한 경우 항상 다이아몬드를 사용할 수 있습니다. 때로는 유일한 방법입니다.

더 나은 수업 디자인을 제안합니다. 여러 상속을 통해 가장 잘 해결되는 몇 가지 문제가 있다고 확신하지만 먼저 다른 방법이 있는지 확인하십시오.

그렇지 않은 경우 가상 함수/인터페이스를 사용하십시오.

대표단에 의한 상속을 사용하십시오. 두 클래스는 기본 A를 가리 키지 만 A로 리디렉션되는 메소드를 구현해야합니다. A의 보호 된 구성원을 B, C 및 D의 "개인"멤버로 돌리는 부작용이 있지만 이제는 그렇지 않습니다. 가상이 필요하고 다이아몬드가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top