0

あるレベルのコントローラーの「親」クラスが多数の「子」クラスの作成/指示を担当する階層クラス構造を探しています。親クラスは、作成する各子を直接参照できる必要があり、各子はその親を直接参照できる必要があります(この子が他のクラスの親でもない場合は、その親のみ)。これにより、親を介して兄弟を参照できます。このパラダイムは、JavaやC#などのJITコンパイル言語で役立つことがわかりましたが、C++には固有の問題があります...

このパラダイムを実装する最初の試みは次のとおりです。

親クラスTreeRoot.h

#ifndef __CCPP_SCENE_H__
#define __CCPP_SCENE_H__
#include "ChildA.h"
#include "ChildB.h"

class TreeRoot : 
{
private:


ChildA* a;
ChildB* b;

public:

//member getters
ChildA* getA();
ChildB* getB();
};

#endif // __CCPP_SCENE_H__

子クラスChildA.h

#ifndef CHILDA_H_
#define CHILDA_H_


#include "TreeRoot.h"


class ChildA
{

private:
TreeRoot* rootScene;

public:
ChildA(TreeRoot*);
~ChildA(void);

TreeRoot* getRootScene();
void setRootScene(TreeRoot*);

};

#endif /*CHILDA_H_*/

子クラスChildB.h

#ifndef CHILDB_H_
#define CHILDB_H_


#include "TreeRoot.h"


class ChildB
{

private:
TreeRoot* rootScene;

public:
ChildB(TreeRoot*);
~ChildB(void);

TreeRoot* getRootScene();
void setRootScene(TreeRoot*);

};

#endif /*CHILDB_H_*/

もちろん、循環インクルードのためにコンパイルされません(TreeRoot.hにはChildA.hとChildB.hが含まれ、どちらにもTreeRoot.hなどが含まれます)。代わりに前方宣言を使用してみました。

親クラスTreeRoot.h

#ifndef __CCPP_SCENE_H__
#define __CCPP_SCENE_H__
#include "ChildA.h"
#include "ChildB.h"

class TreeRoot : 
{
private:


ChildA* a;
ChildB* b;

public:

//member getters
ChildA* getA();
ChildB* getB();
};

#endif // __CCPP_SCENE_H__

子クラスChildA.h

#ifndef CHILDA_H_
#define CHILDA_H_


//#include "TreeRoot.h" //can't use; circular include!
class TreeRoot;

class ChildA
{

private:
TreeRoot* rootScene;

public:
ChildA(TreeRoot*);
~ChildA(void);

TreeRoot* getRootScene();
void setRootScene(TreeRoot*);

};

#endif /*CHILDA_H_*/

子クラスChildB.h

#ifndef CHILDB_H_
#define CHILDB_H_


//#include "TreeRoot.h" //can't use; circular include!
class TreeRoot;



class ChildB
{

private:
TreeRoot* rootScene;

public:
ChildB(TreeRoot*);
~ChildB(void);

TreeRoot* getRootScene();
void setRootScene(TreeRoot*);

};

#endif /*CHILDB_H_*/

この実装は、メッセージを子オブジェクトに正常にブロードキャストし、次のように子オブジェクトから親クラスへのコールバックを実行できるという点でほぼ機能します。

TreeRoot.cpp

...
a->someChildMethod();
a->getRootScene()->someParentMethod();

しかし、私が次のことを試してみると:

ChildA.cpp

...
rootScene->someParentMethod(); //ERROR C2027: use of undefined type TreeRoot

未定義の型エラーが発生します。上記のように前方宣言を使用しても、TreeRootが実際に何であるかはコンパイラに通知されないため、これは理にかなっています。問題は、上記のrootScene-> someParentMethod()呼び出しのような子オブジェクトからの呼び出しを有効にするにはどうすればよいですか?おそらく、テンプレートを介してジェネリック型を使用すると、コンパイラーが満足し、私が探している機能を提供できるでしょうか?

ありがとう、CCJ

4

4 に答える 4

2

すべてのファイルで前方宣言を使用し.hます。ポインタをクラスメンバーとしてのみ格納しているため、これを行うことができます。したがって、完全なクラス宣言は必要ありません。

次に、対応するすべての.cppファイルで#include、必要なクラスのヘッダーファイルを作成します。

したがって、TreeRoot.h前方宣言ChildAChildB。でTreeRoot.cpp、あなた#include ChildA.hChildB.h

他の2つのクラスについて、すすぎ、繰り返します。

これで現在の問題は解決しますが、この設計はせいぜい不安定に見えることに注意してください。

于 2012-08-06T16:31:33.510 に答える
1

「TreeRoot.h」をChildAファイルとChildBファイルに含めてみてください。また、ポリモーフィズムを使用して、共有動作のためにAとBが継承する親クラスを作成することをお勧めします。

于 2012-08-06T16:29:31.167 に答える
1

これにはヘッダーファイルをいじる必要はありませんが、私の提案:すべてのノードを同じクラスにする(柔軟性を高める[ツリーを別のツリーのサブツリーにする場合はどうすればよいですか?ルートノードのクラスを最初のツリーから子クラスに変更します]、そして少なくとも私の考えでは、より理にかなっている/よりエレガントに見える/量を減らしたり、記述しなければならないコードを単純化したりします)、または親ノードクラスと子ノードクラスの両方にスーパークラスを使用します(ATaylorが示唆しているように)が、親ノードと子ノードが、形成に必要な機能を超える多くの異なる機能を備えている場合にのみ、より良い解決策になると思います。ツリー構造。

于 2012-08-06T16:30:07.030 に答える
0

ChildA.cppファイルでは、親ヘッダーを次のように含める必要があります。

#include "TreeRoot.h"
于 2012-08-06T16:30:37.660 に答える