使用C ++中的混合函数进行奇怪的循环继承

时间:2012-07-03 12:46:02

标签: c++ templates circular-dependency mixins crtp

在这里解读循环继承的好方法是什么?

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通过它 其构造函数中thisHasImportance。这条路, HasImportance根本不需要继承;它只是存储一个 指向(ahem)本身的指针,以及模板参数提供的类型 指针。 (3)使Node成为类模板,如下所示:

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

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

编译并且它没有引入this的无偿副本, 但似乎......有点太好奇了。

这里有代码味道吗?我应该完全接近这些图表 不同的方式?

1 个答案:

答案 0 :(得分:1)

(3)但有点不同。

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

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

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

对我来说看起来非常简单,并不比CRTP本身更好奇。