質問

だから私はC ++でこのようなツリークラスを持っているとします

class Node{
    void addChild(Node*);
    /*obvious stuff*/
    protected:
        Node* parent;
        vector<Node*> children
}

class specialNode : public Node{
    void addChild(specialNode*);
    /*obvious stuff*/
    /*special stuff*/
}

今、私がSpecialTreeで子供たちにアクセスするたびに、私は明らかにSpecialNode*ではなくノード*を取得します。

ただし、このSpecialNode*には、ノードにはないメンバー変数と機能があります。

SpecialNodeにSpecialNodeを子供としてしか使用しないように強制することができますが、そうでなければコンパイル時間で壊れますが、子供/親にアクセスするときはノード*を取得します。

賢いことはありますか、それともこれを進めるためのより良い方法はありますか?文字通り毎回キャストする以外は?

役に立ちましたか?

解決

必要な場合だけ SpecialNode ツリー内のオブジェクト(そして、すべての一般的なツリー機能をカプセル化したいだけです Node)あなたは作ることができます Node いわゆる「ミックスイン」クラスのような

template <class N>
class Node : public N {
public:
  void addChild(Node<N>*);
protected:
  Node<N>* parent;
  vector<Node<N>*> children;
};

class SpecialNodeBase {
  // Here comes all "special" data/methods for your "special" tree
};

typedef Node<SpecialNodeBase> SpecialNode;

その後、あなたはの木を構築することができます SpecialNode オブジェクトとすべてのメソッドを使用します SpecialNodeBase からの追加のツリー管理機能もあります Node

他のヒント

子供のクラスのaddChild関数は多型ではないため、仮想にしますが、ベース/チャイルドメンバー間の過負荷機能は許可されていないため、子クラスのaddChildパラメーターを変更する必要があります。

class Node{
    virtual void addChild(Node*);
    ...
}

class specialNode : public Node{
    virtual void addChild(Node*);
    ...
}

今、それは機能するはずです。


にアクセスしたい場合 childeren チャイルドクラスの変数(specialNode クラス)、キャストする必要があります。例えば:

specialNode* var = static_cast<specialNode*>(children[i]);

AddChildを仮想関数として宣言したので、使用する必要があります dynamic_cast それ以外の static_cast わからない場合 children[i] 常にのインスタンスです specialNode クラス、したがって使用する方が良いです dynamic_cast:

specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
    //...
}

私が正しく理解していれば、「ミックスイン」クラスのソリューションはあなたに電話することができません addChild によって実装された関数から SpecialNodeBaseClass.

あなたは実際に次のことをすることができます:

template <class recursiveT>
class Base {
public:

     Base(dataType data) { populate children with data; }

     void addChild() { something base class appropriate; }

protected:
     std::vector<recursiveT> children;
};




class Derived: public Base<Derived> {
public:
     /* note: the constructor here will actually call the 
        constuctor of the base class */
     Derived(dataType data) : Base<Derived>(data) {} 
     /* other special functions go here.  */
};

これは少しクレイジーに見えるかもしれませんが、いくつかのGCCバージョンで私のためにきれいに編集するので、それが完全に間違っていないと信じています。これで、内部派生からベースの関数を呼び出すことができるはずです。

あなたは間違いなくキャストする必要があります Node *specialNode * ある時点で、ただし、これを1か所で実行することで、これを清潔で簡単に管理できるようにすることができます。メンバー関数を追加することができます getParent そしてそれをオーバーライドします specialNode, 、 このような:

class Node {
  ...
  virtual Node *getParent() {
    return parent;
  }
};

class specialNode : public Node {
  ...
  specialNode *getParent() {
    return dynamic_cast<specialNode *>(parent);
  }
};

もちろん、これはそれを前提としています specialNodesは常に他のものを持っています specialNodes親/子供として。混ぜる場合 NodespecialNodeS、これは明らかに機能しません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top