2009-11-19 1 views
2

나는 문제가 관계의 유형을 모델링하는 방법을 결정하는 데 문제가 있습니다 ... 모델링 "옵션"상속

어떤 일을하고 (등 속도, 건강,) 어떤 일을 할 수 있습니다 모든 상사

그래서이 "주"추상 보스 클래스의 일부입니다.

class Boss // An abstract base class 
{ 
    //Stuff that all Bosses can do/have and pure virtual functions 
}; 

이제는 촬영할 수있는 보스에 대해 몇 가지 순수 가상 기능과 멤버를 지정하고자합니다. 어떻게 모델링해야하는지 궁금합니다. 나는 Boss 클래스에서 ShootingBoss 클래스를 파생시키는 것을 고려해 봤지만, 특정 보스는 그 자체로 클래스입니다 (보스는 파생 된 추상 기본 클래스입니다.) 따라서 ShootingBoss가 Boss에서 파생되고 특정 보스가 ShootingBoss, 보스는 Boss 클래스의 보호 된 데이터에 액세스 할 수 없습니다.

Boss(ABC) -> ShootingBoss(ABC) -> SomeSpecificBoss(can't access protected data from Boss?) 

기본적으로 나는 이것을 모델로 추천하는 방법이 무엇인지 궁금합니다. 어떤 도움을 주셔서 감사합니다. 더 많은 정보가 필요하다면, 나는 기꺼이 제공 할 것이다.

+1

SomeSpecificBoss는 Boss의 보호 된 구성원을 액세스 할 수 있습니다. SomeSpecificBoss가 어떻게 든 파생되는 한 직접 파생되지는 않습니다. – hirschhornsalz

+0

감사합니다. 웬일인지 나는 보호가 단지 1 단계 아래로 갔다라고 생각했다. – Anonymous

+0

@drhirsch - 실제로 ShootingBoss가 Boss에서 개인적으로 상속 된 경우 SomeSpecificBoss는 Boss의 보호 된 구성원 중 하나에 액세스 할 수 없습니다. – LeopardSkinPillBoxHat

답변

2

나는 Mixin 클래스를 조사해야한다고 생각합니다.

예를 들어, 다음과 같은 클래스를 만들 수 있습니다

class Boss { 
    // Here you will include all (pure virtual) methods which are common 
    // to all bosses, and all bosses MUST implement. 
}; 

class Shooter { 
    // This is a mixin class which defines shooting capabilities 
    // Here you will include all (pure virtual) methods which are common 
    // to all shooters, and all shooters MUST implement. 
}; 

class ShootingBoss : public Boss, public Shooter 
{ 
    // A boss who shoots! 
    // This is where you implement the correct behaviour. 
}; 

유지 mixin은 multiple inheritance가 사용되는 요구하고, 그렇게 많은 함정과 복잡성이있다. 이 함정을 피하기 위해 this one과 같은 질문에 대한 대답을 살펴 보시기 바랍니다.
1) 믹스 인 클래스 (이미 설명)
2) 역할 재생 클래스 :이 일을 두 가지 방법이있다

+0

감사합니다. 그럼에도 불구하고이 작업이 제대로 수행되는지는 잘 모르겠지만 유용한 조언입니다. – Anonymous

1

왜 인터페이스를 사용하지 않습니까? 그래서, 단순히 기본 클래스보다 위버, 당신은 능력을 귀하의 물건을 펼쳐.

struct IBoss : public IObject 
{ 
} 
struct ICanShoot : public IObject 
{ 
} 

일반적으로 이것을 구현하려면 인터페이스를 쿼리 할 수있는 다른 인터페이스에서 인터페이스를 파생시킵니다.

class Boss : public IBoss, public ICanShoot 
{ 
}; 

그것은 일부 과잉 될 수도 있지만 수업 heirachy 모두 망쳐 경우,이 혼란 중 가장 좋은 방법은 다음과 같습니다

struct IObject 
{ 
int getId(); // returns a unique ID for this interface. 
int addRef(); 
int release(); 
bool queryInterface(int id, void** pp); 
} 

그런 식으로, 당신은보다 쉽게 ​​보스를 구현 .

M $의 IUnknown 인터페이스를 살펴보십시오.

+0

IObject의 하위 클래스는 부모를 가상으로 선언해야합니다. 그렇지 않으면 다중 상속이 불가능합니다. 그럼에도 불구하고 IObject와 함께 기본이 아닌 생성자를 사용해야하는 경우 정말 복잡해질 것입니다. – Gayan

1

있습니다.
역할 연기는 장점과 단점이 있습니다. 역할, 그 객체는 (보스, 사수, 뭐든간에) 봉쇄를 사용하여 구현할 수 있습니다. 공통 기본 인터페이스 클래스에서 파생되어야합니다.이 클래스는 동태 적으로 다운 캐스팅되어야합니다 (아 ..). 호출자는 클래스의 객체에 역할 포인터 (다운 캐스트가 들어올 곳)를 물어보고 객체가 역할 (반환 된 비공유 포인터)을 재생할 수 있으면 클라이언트가 역할의 적절한 기능을 호출합니다. 역할 재생 접근법의 주요 이점 (다중 상속을 피할 때 appart) - 동적입니다. Object는 컴파일 타임에 정의되어야하는 mixin과 달리 런타임에 새로운 역할을 받아 들일 수 있습니다.
또한 확장 가능합니다.다중 상속 (믹스 인) 접근 방식에서는 "Protector"로 계층 구조를 확장 Boss, ShootingBoss는, ProtectingBoss는, ShootingProtectingBoss가, 나중에 Сoward (Boss, ShootingBoss, ProtectingBoss, ShootingProtectingBoss, CowardBoss 함께 ufrther 확장하는 상사가 간단 할 수있다라고하기로 결정한 경우 , CowardShootingBoss, CowardProtectingBoss, CowardShootingProtectingBoss) - 계층 구조가 폭발하는 것을 볼 수 있습니다. 이것은 객체가 새로운 역할 Coward을 받아 들여야 만하는 역할 재생 모델로 전환해야 할 때입니다. 그러나 필요할 때까지 mixin 클래스를 고수하십시오. 다음은 역할 재생 사례에 대한 계층 적 스케치입니다.

class IRole 
{ 
// some very basic common interface here 
public: 
virtual ~IRole() {} 
}; 

class IBoss : public IRole 
{ 
}; 

class IShooter : public IRole 
{ 
}; 

class IProtector : public IRole 
{ 
}; 

class MultifunctionalPerson 
{ 
public: 
bool AcceptRole(IRole* pRole); // pass some concrete role here 
IRole* GetRole(int roleID); 
}; 


// your clinet will be using it like that 
MultifunctionalPerson& clPerson = ... (coming from somewhere); 

// dynamic_cast below may be replaced with static_cast if you are sure 
// that role at PROTECTOR_ROLE location is guaranteed to be of IProtector type or NULL 
IProtector* pProtector = dynamic_cast<IProtector*>(clPerson.GetRole(PROTECTOR_ROLE)); 
if(0 != pProtector) 
{ 
pProtector->DoSomething(); 
}