6

ここで循環継承を解読する良い方法は何ですか?

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)次のようにクラス テンプレートを作成します。thisHasImportanceHasImportanceNode

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

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

それはコンパイルされ、 の不当なコピーは導入されませんがthis、少し奇妙すぎるようです。

ここにコードの匂いはありますか?これらのグラフにまったく異なる方法でアプローチする必要がありますか?

4

1 に答える 1

1

(3) でもちょっと違う。

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

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

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

CRTP自体よりも興味がなく、私には完全に簡単に見えます。

于 2012-07-03T14:32:54.383 に答える