【问题标题】:Curious circular inheritance with mix-ins in C++C++ 中带有混入的奇怪循环继承
【发布时间】:2012-07-03 12:46:02
【问题描述】:

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

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&lt;NodeType*&gt;。 (2)TrafficLight通过其 thisHasImportance 在其构造函数中。这边走, HasImportance 根本不需要继承;它只存储一个 指向 (ahem) 本身的指针,模板参数提供了 指针。 (3) 将Node 设为类模板,如下所示:

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

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

编译后它不会引入this 的免费副本, 不过好像……有点太好奇了。

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

【问题讨论】:

  • 在 CRTP 中使用static_cast&lt;NodeType*&gt;(this)正常
  • @KennyTM:我什至会说这是使用 CRTP 的关键
  • 谢谢。我对使用 static_cast 感到畏缩,因为我似乎忽略了一个迹象(一种“气味”),表明更深层次的东西是错误的。如果它在 CRTP 中是“正常的”,我想我不会抗拒这么多。这是我的第一个 CRTP。你能告诉? :)

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


【解决方案1】:

(3) 但有点不同。

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

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

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

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

【讨论】:

  • 谢谢!我更喜欢这个,即使它是一个很小的差异。与我的版本不同,mix-ins 的“编译时接口”现在很简单,并且不受代码中其他地方的更改的影响。
猜你喜欢
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
相关资源
最近更新 更多