C ++无法建立对“父”对象的句柄引用 - 循环包含或未定义的类型错误

时间:2012-08-06 16:25:00

标签: c++ c compiler-construction

我希望有一个层次结构的类结构,其中一级控制器“父”类负责创建/指导一些“子”类。父类应该能够直接引用它创建的每个子节点,并且每个子节点应该能够直接引用它的父节点(并且假设这个子节点不是更多类的父节点,只有它的父类)。这允许通过父级引用兄弟姐妹。我发现这个范例在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__

Child class 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_*/

Child class 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__

Child class 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_*/

Child class 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 个答案:

答案 0 :(得分:2)

在所有.h个文件中使用转发声明。您可以这样做,因为您只是将指针存储为类成员,因此您不需要完整的类声明。

然后,在所有相应的.cpp个文件中,#include您需要的类的头文件。

因此,在TreeRoot.h中,您转发声明ChildAChildB。在TreeRoot.cpp,您#include ChildA.hChildB.h

为其他2个班级冲洗并重复。

请注意,这将解决您当前的问题,但这种设计充其量只是片状。

答案 1 :(得分:1)

您可以尝试在ChildA和ChildB文件中包含“TreeRoot.h”。我还建议使用Polymorphism并创建一个父类,A和B继承它,用于共享行为。

答案 2 :(得分:1)

这不涉及摆弄头文件,但我的建议是:让所有节点都成为同一个类(提供更大的灵活性[如果你决定要将树变成另一棵树的子树怎么办?你' d必须将根节点的类从第一个树更改为子类],至少在我看来,更有意义/似乎更优雅/会减少你的代码量和/或简化代码必须编写),或者为父节点类和子节点类使用超类(如ATaylor建议的那样),尽管我觉得如果你的父节点和子节点有很多不同的功能,它们只会是一个更好的解决方案。形成树形结构。

答案 3 :(得分:0)

在ChildA.cpp文件中,您必须将父标题包含为

#include "TreeRoot.h"