在这里解读循环继承的好方法是什么?
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),因为TrafficLight
是一个不完整的类型
当HasImportance
尝试继承它时。
真正的问题是HasImportance需要知道返回的类型
neighbors()
。如果HasImportance
继承自
Node
,然后它认为neighbors()
会返回一个列表
Node*
,而不是TrafficLight*
,因此没有
知道它可以在项目上调用receive_importance()
。类似
如果HasImportance
根本没有继承,则会出现问题。
class TrafficLight : public HasImportance, HasState<3>,
virtual Node { }
。
我想出了三种方法来解决这个问题,但看起来都很难看。 (1)
static_cast<NodeType*>
。 (2)TrafficLight
通过它
其构造函数中this
到HasImportance
。这条路,
HasImportance
根本不需要继承;它只是存储一个
指向(ahem)本身的指针,以及模板参数提供的类型
指针。 (3)使Node
成为类模板,如下所示:
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /* ... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ }
编译并且它没有引入this
的无偿副本,
但似乎......有点太好奇了。
这里有代码味道吗?我应该完全接近这些图表 不同的方式?
答案 0 :(得分:1)
(3)但有点不同。
template <class NodeType>
class Node { ... };
template<class NodeType>
class HasImportance : public virtual Node<NodeType> { ... };
class TrafficLight : public HasImportance<TrafficLight> { ... };
对我来说看起来非常简单,并不比CRTP本身更好奇。