C ++类,其基类和循环包含

时间:2009-10-31 17:57:10

标签: c++ include

文件#1(foo.h):

#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif

文件#2(bar.h):

#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif

文件#3(baseclass.h):

#ifndef BASECLASS_H_
#define BASECLASS_H_
#include "foo.h"
class Foo;
class baseclass {
public:
list<Foo*> L;
};
#endif

但我在第class Foo : public baseclass行的文件#1中收到编译错误:

Error: expected class-name before »{« token

如果我添加class baseclass; bevor类声明,我会收到此错误:

Error: invalid use of incomplete type »struct baseclass«

所以我的问题是,如何解决基类的循环依赖?

询问你是否得到某些观点。我已经尝试改变包含标题的顺序,但到目前为止没有运气。 谢谢你的提示。

编辑:注意:我正在使用包含警卫 EDIT2:它不仅限于指针,所以我删除它们,以防万一。 EDIT3:添加了基类(忘了O.o) 编辑4:现在应该清楚,没有任何缺陷,这个问题会持续存在。

5 个答案:

答案 0 :(得分:4)

通常的方法是在头文件周围添加以下内容:

#ifndef FOO_H_
#define FOO_H_
#include "baseclass.h"
#include "bar.h"
class Bar;
class Foo : public baseclass {
public:
bar *varBar;
};
#endif

#ifndef BAR_H_
#define BAR_H_
#include "foo.h"
class Foo;
class Bar {
public:
Foo *varFoo;
};
#endif

大多数编译器(gcc,VC)也在文件开头接受#pragma once,但我很确定它不是当前C ++标准的一部分。


编辑:

果然,正如ISO / IEC 14882所述,#pragma“causes the implementation to behave in an implementation-defined manner. Any pragma that is not recognized by the implementation is ignored.

目前C ++ 0x仍然相同。

所以我会坚持使用第一种老式的做法; - )

答案 1 :(得分:3)

您似乎发布的内容是Bar中有Foo成员,Foo中有Bar成员。这是一个你需要打破的循环依赖 - 如果每个Foo都包含一个包含Bar的{​​{1}},那么构造永远不会终止。

Foo

相反,您需要在至少其中一个中使用指向class Foo : public baseclass { public: Bar varBar; }; class Bar { public: Foo varFoo; }; Foo的指针或引用:

Bar

由于循环性被破坏并且您只使用对象的引用,因此您不需要具有引用类型的完整定义,并且可以使用前向声明。

包含防护对用户有好处,但在开发时尽量不要依赖它们。如果编译器必须检查是否已包含某些内容,即使它对guards / pragma进行了优化,它仍然可以正常工作。你需要了解什么取决于什么打破了初始周期,并且在文件上放置保护对你没有帮助。

答案 2 :(得分:2)

你的标题上是否包含警戒?上面的代码递归地包含a.h和b.h,从而定义了一大堆标题。

前向声明class b;消除了对FILE1中#include "b.h"的需求。同样,应从FILE2中删除#include "a.h"

答案 3 :(得分:2)

#ifndef _BAR_H_
#define _BAR_H_    
#include "baseclass.h"

class Bar;
class Foo : public baseclass {
public:
    Bar *varBar;
};

#endif

如果一个类是前向声明的,并且您只使用指针或对该类成员的引用,那么您不需要为其包含标题。另一个文件中的类也是如此。但是,请确保在所有头文件(#ifndef...#endif)中使用包含保护,以防止在编译期间多次包含头文件。

答案 4 :(得分:0)

baseclass.h不需要foo.h中的任何内容,因此请从#include "foo.h"移除baseclass.h

Foo中有一个Bar变量,Bar中有一个Foo。这不会起作用:你不能在一个盒子里装一个鸡蛋一个鸡蛋盒子。其中一个或两个应该是一个指针。