2012-07-03 3 views
6

여기에서 원형 상속을 푸는 좋은 방법은 무엇입니까? HasImportance 시도가 상속 할 때 TrafficLight이 불완전한 유형 때문에C++의 믹스 인을 이용한 호기심 원형 상속

class Node { 
    // ... 
public: 
    list<Node*> neighbors() { /* ... */ } 
    void update() { } 
} 

template<class NodeType> 
class HasImportance : public virtual NodeType { 
    double m_importance = 0.0; 
public: 
    void receive_importance(double imp) { /* ... */ } 
    void give_importance() { 
     for (auto neighbor : this->neighbors()) 
     neighbor->receive_importance(m_importance /* ... */); 
    } 
}; 

class TrafficLight : public HasImportance<TrafficLight>, virtual Node { 
public: 
    list<TrafficLight*> neighbors() { ... } 
    void update() { give_importance(); /* ... */ } 
}; 

그것은 (GCC 4.7.0)를 실패합니다.

실제 문제는 HasImportance가 neighbors()이 반환 한 형식을 알아야한다는 것입니다. Node에서 HasImportance 상속은, 다음은 항목에 receive_importance()를 호출 할 수 있다는 것을 알고하지 않는 결과 neighbors() 반환 Node*의 목록이 아니라 TrafficLight*을 생각하고합니다. HasImportance이 전혀 상속되지 않는 경우 문제가 발생합니다.

내가 취하려고하는 것은 다양한 종류의 그래프를 쉽게 정의하고 각각의 믹스 인을 개별적으로 테스트하는 데 도움이되는 몇 가지 믹스 인을 만드는 것입니다. 예를 들어, 의 경우, class TrafficLight : public HasImportance, HasState<3>, virtual Node { }과 같이 을 쓰면 신호등 그래프의 노드 클래스를 정의 할 수 있어야합니다.

나는 이것을 해결하는 세 가지 방법을 생각해 냈지만, 모두보기 흉하게 보입니다. (1) static_cast<NodeType*>. (2) TrafficLight은 생성자에 this ~ HasImportance을 전달합니다. 이렇게하면 HasImportance은 전혀 상속 할 필요가 없습니다. 포인터를 (ahem) 자체에 저장하고 템플릿 매개 변수는 포인터의 유형을 제공합니다. 컴파일

template<class NodeType> 
class Node { 
public: 
    list<NodeType*> neighbors() { /* ... */ } 
} 

class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ } 

을 그리고 this, 의 무상 사본을 도입하지 않고 것 같습니다 ... 조금 너무 궁금 : (3)이 같은 Node 클래스 템플릿을 확인합니다.

코드 냄새가 있습니까? 이 그래프를 완전히 다른 방식으로 접근해야합니까?

+11

CRTP에서 'static_cast (this)'을 (를) * 정상 *로 사용하고 있습니다. – kennytm

+0

@KennyTM : 나는 지금까지 가서 CRTP를 사용하는 열쇠라고 말할 것입니다. – PlasmaHH

+0

고마워요. static_cast를 사용할 때 나는 징조 ("냄새")를 무시하고있는 것처럼 보입니다. 왜냐하면 더 깊은 것이 잘못되었다고 생각하기 때문입니다. 그것이 CRTP에서 "정상적인"것이라면, 나는 그렇게 많이 저항하지 않을 것이라고 생각합니다. 이것은 내 첫 번째 CRTP입니다. 너 말해 줄 수있어? :) –

답변

1

(3) 그러나 약간 다르게.

template <class NodeType> 
class Node { ... }; 

template<class NodeType> 
class HasImportance : public virtual Node<NodeType> { ... }; 

class TrafficLight : public HasImportance<TrafficLight> { ... }; 

CRTP 자체보다 더 호기심이없는 것처럼 보입니다.

+0

고마워요! 나는 그것이 작은 차이 일지라도 훨씬 더 좋아한다. 믹스 인에 대한 "컴파일 타임 인터페이스"는 이제 내 버전과 달리 코드의 다른 곳에서의 변경 사항에 대해 간단하고 매우 안전합니다. –