文件#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:现在应该清楚,没有任何缺陷,这个问题会持续存在。
答案 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
。这不会起作用:你不能在一个盒子里装一个鸡蛋和一个鸡蛋盒子。其中一个或两个应该是一个指针。