여기에서 원형 상속을 푸는 좋은 방법은 무엇입니까? 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
클래스 템플릿을 확인합니다.
코드 냄새가 있습니까? 이 그래프를 완전히 다른 방식으로 접근해야합니까?
CRTP에서 'static_cast (this)'을 (를) * 정상 *로 사용하고 있습니다. –
kennytm
@KennyTM : 나는 지금까지 가서 CRTP를 사용하는 열쇠라고 말할 것입니다. – PlasmaHH
고마워요. static_cast를 사용할 때 나는 징조 ("냄새")를 무시하고있는 것처럼 보입니다. 왜냐하면 더 깊은 것이 잘못되었다고 생각하기 때문입니다. 그것이 CRTP에서 "정상적인"것이라면, 나는 그렇게 많이 저항하지 않을 것이라고 생각합니다. 이것은 내 첫 번째 CRTP입니다. 너 말해 줄 수있어? :) –