3

여러 클래스 (상속 사용)가있는 응용 프로그램이 있다고 가정합니다 언젠가 내 응용 프로그램에 새 사양을 추가해야합니다. 다중 상속.DIAMOND 현재 응용 프로그램의 기능을 확장하고자하는 경우

예를 들어,이 코드 :

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

지금 내 새로운 기능이 작업을 수행하기 위해 저를 필요 :

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

하지만이 다이아몬드 문제로 이어질 것입니다.

내 질문은이 문제를 극복하는 방법입니다. 1) 모범 사례로서 앞으로 여러 상속을 사용해야 할 수도 있다고 가정하고 모든 클래스에 가상 상속을 사용하겠습니까? 또는 2) 코드를 변경하고 필요한 경우 언제든지 기본 클래스를 가상으로 변경합니다.

+0

귀하의 ** Y ** 상속은 반드시 문제가되지 않습니다. 'D '를'A'로 위협해야합니까? – Jarod42

+0

가상 상속에는 특히 전체 계층에서 필요한 생성자에 대한 몇 가지 강력한 제약이 있습니다. – Jarod42

+1

본 적이 있습니까 (http://stackoverflow.com/a/407928/2721583)? 구체적인 기본 클래스 대신 인터페이스를 사용하도록 코드를 수정할 수 있습니다. –

답변

1

이 문제를 극복하는 좋은 방법 중 하나는 클래스에서 가져 오려고하는 동작을 구성 요소로 분리하는 것입니다.

은 지금이

class A {} 
class B : public A {some behavior X} 
class C : public A {some behavior Y} 
class D : public ? {I need X and Y plus some behavior Z} 

한 (잠재적으로 나쁜)이 단지 당신이 다른에서 필요한 동작을 복사 한 후 B 또는 C와에서 확장하는 해결 방법하지만,이 같은 상황이 코드를 복제 중입니다. 당신이 할 수 있습니다 무엇

구성 요소로 행동을하는 것입니다 : 이것은 우리가 인터페이스를 호출 할 수있는 순수 가상 클래스가 될 것

class Behavior {void behave() = 0} 

. 당신은 할 수 :

class D : public A {BehaviorX, BehaviorY, BehaviorZ, ...} 

당신이 정말로 구성 요소 모델링을하고 싶었다면 : 당신은에서 확장하는 새로운 클래스를 만들하지만 당신이 선택하고 그들이 가지고있는 행동들을 선택할 수 있습니다에

class BehaviorX : public Behavior {void behave(){behavior x}} 
class BehaviorY : public Behavior {void behave(){behavior y}} 
class BehaviorZ : public Behavior {void behave(){behavior z}} 

이 허용 것 다음 단계로 아이들 수업을 모두 없애고 클래스 A를 사용할 수있는 구성 요소 가방으로 사용하면 꿈꾸는 모든 행동을 사용할 수 있습니다. 그러면 원하는 곳 어디에서나 새로운 "수업"을 만들 수 있습니다. 당신이 원하는 행동을하십시오 :

A likeB = new A(BehaviorX); 
A likeC = new A(BehaviorY); 
A likeD = new A(BehaviorX, BehaviorY, BehaviorZ); 
A likeE = new A(BehaviorY, BehaviorZ, Behavior?);