2

したがって、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* ではなく Node* が取得されます。

しかし、この specialNode* には、Node にはないメンバー変数と関数があります。

specialNode が子としてのみ specialNode を取得し、それ以外の場合はコンパイル時に中断するように強制することはできますが、子/親にアクセスするときに Node* を取得し、specialNode 関数であっても、特別な関数を使用するときはいつでもそれをキャストする必要があります。

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

4

4 に答える 4

4

ツリー内のオブジェクトのみが必要な場合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

于 2010-08-17T23:02:05.297 に答える
0

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バージョンできれいにコンパイルされるので、完全に間違っているわけではないと私は信じる傾向があります。これで、Derivedの内部からBaseの関数を呼び出すことができるはずです。

于 2011-02-12T00:52:02.613 に答える
0

子クラスの addChild 関数はポリモーフィズムではないため、仮想化しますが、基本/子メンバー間での関数のオーバーロードは許可されていないため、子クラスの addChild パラメータを変更する必要があります。

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

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

これで、動作するはずです。


childeren子クラス ( class ) から変数にアクセスする場合specialNodeは、キャストする必要があります。例えば:

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

addChild を仮想関数として宣言したので、それが常にクラスのインスタンスであると確信できない場合はdynamic_cast代わりに使用する必要があるため、使用する方が適切です。static_castchildren[i]specialNodedynamic_cast

specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
    //...
}
于 2010-08-17T22:59:23.647 に答える
-1

ある時点で間違いなくNode *を aにキャストするspecialNode *必要がありますが、これを 1 か所で行うだけで、これをクリーンで管理しやすくすることができます。次のように、メンバー関数を追加して、getParentでオーバーライドすることができますspecialNode

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

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

もちろん、これはspecialNodes が常に他specialNodeの s を親/子として持っていることを前提としています。Nodes とsを混在させるとspecialNode、これは明らかに機能しません。

于 2010-08-17T23:01:33.470 に答える