C ++は、自己参照である派生クラスを処理します
-
29-09-2019 - |
質問
だから私は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);
}
};
もちろん、これはそれを前提としています specialNode
sは常に他のものを持っています specialNode
s親/子供として。混ぜる場合 Node
砂 specialNode
S、これは明らかに機能しません。