ここで循環継承を解読する良い方法は何ですか?
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(); /* ... */ }
};
継承しようとするとTrafficLight
不完全な型であるため、失敗します(gcc 4.7.0) 。HasImportance
本当の問題は、HasImportance が によって返される型を知る必要があること
neighbors()
です。HasImportance
から継承する
場合、 ではなくのリストを返す
Node
と考え、その結果、アイテムを呼び出すことができるかどうかを知りません。まったく継承しない場合も同様の問題があります。neighbors()
Node*
TrafficLight*
receive_importance()
HasImportance
ところで、私がやろうとしているのは、さまざまな種類のグラフを簡単に定義し、各ミックスインを個別に単体テストするのに役立ついくつかのミックスインを作成することです。たとえば、次のように書くだけで、信号機のグラフのノード クラスを定義できるはずですclass TrafficLight : public HasImportance, HasState<3>,
virtual Node { }
。
これを解決する 3 つの方法を考え出しましたが、どれも醜いようです。(1)
static_cast<NodeType*>
. (2)そのコンストラクターでにをTrafficLight
渡し
ます。この方法で
は、継承する必要はまったくありません。(ahem)自体へのポインターを格納するだけで、テンプレートパラメーターはポインターの型を提供します。(3)次のようにクラス テンプレートを作成します。this
HasImportance
HasImportance
Node
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /* ... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ }
それはコンパイルされ、 の不当なコピーは導入されませんがthis
、少し奇妙すぎるようです。
ここにコードの匂いはありますか?これらのグラフにまったく異なる方法でアプローチする必要がありますか?