C++ 包含标题的一些规则是什么?

C++ 包含标题的一些规则是什么?,c++,include,C++,Include,我的程序越大,我就会不断遇到问题。例如,我得到以下错误: In file included from WidgetText.h:8, from LCDText.h:17, from WidgetText.cpp:13: Generic.h:21: error: expected class-name before ',' token 以下是这些台词: #include "Generic.h" // WidgetText.h:8

我的程序越大,我就会不断遇到问题。例如,我得到以下错误:

In file included from WidgetText.h:8,
                 from LCDText.h:17,
                 from WidgetText.cpp:13:
Generic.h:21: error: expected class-name before ',' token
以下是这些台词:

#include "Generic.h" // WidgetText.h:8

#include "WidgetText.h" // LCDText.h:17

#include "LCDText.h" // WidgetText.cpp:13

class Generic: public virtual LCDText, public CFG, public virtual Evaluator { // Generic.h:21
以下是各种头文件的内容:

//Generic.h
#include "CFG.h"
#include "Evaluator.h"
#include "LCDText.h"
#include "Widget.h"

//WidgetText.h
#include "Generic.h"
#include "Property.h"
#include "Widget.h"

//LCDText.h
class Generic;
#include "LCDBase.h"
#include "WidgetText.h"
这并不能提供太多;我知道。我不知道还包括什么。每个头定义一个以其头命名的类,因此LCDText.h有一个名为LCDText的类


由于与此类似的早期问题,必须将LCDText.h中声明类“Generic”的一行放在那里。我假设当前的问题有一个类似的解决方案,但到目前为止我还没有找到它。

您有一个循环依赖项:Generic.h包括LCDText.h,其中包括WidgetText.h,其中包括Generic.h;错误源于这个基本问题。如果您可以通过修改标题来消除这个循环,那么错误很可能会在重构过程中自行解决,或者问题会变得比现在更加明显。

从这里提供的代码来看,您似乎多次包含标题字段。为了防止出现问题,您需要在头文件中添加条件保护。

解决方案的一部分是添加一些条件保护以消除这些编译器错误(就像您对
类Generic
行所做的那样)。谷歌将提出很多关于如何做到这一点的建议

使用正向声明可以消除此答案中描述的循环/循环
#include
s

前向声明允许包含对前向声明类的引用和指针,并允许将前向声明类作为参数传递,但不允许派生或包含前向声明类的实例成员。因此,您的泛型类需要一种方法来包含LCDText、CFG和Evaluator的头文件。如果由于LCDText、CFG或Evaluator需要
#包含
(而不仅仅是前向声明)Generic而无法做到这一点,则需要重新排列层次结构以解决这一问题(例如,将成员变量设为类的指针或引用,而不是将其设为类的实例)

然而像这样使用多重继承(特别是使用两个虚拟继承所隐含的菱形继承)是一种明确的代码味道。它建议您应该以不同的方式设计类层次结构。例如,您可能需要更倾向于组合而不是继承。这将使清理转发声明和循环依赖关系变得更加容易


编辑:您提到,随着代码库越来越大,您遇到的问题也越来越多。我听说John Lakos是管理大型项目中头文件依赖性等问题的很好参考,尽管对于您的项目现在的位置来说,这可能有些过分。

其他人已经指出了循环依赖关系,但是如果您仍然不确定如何修复它,那么它看起来就像您需要在WidgetText.h(即第8行)中向前声明
Generic

class Generic;

如果你已经试过了,而且听起来好像你已经试过了,然后,您需要检查如何在WidgetText.h中使用
Generic
,并查看是否可以消除依赖完整定义的地方,例如,将聚合
Generic
更改为
Generic*
或将访问
Generic
方法的内联成员移动到源文件。

是否有#ifdef在每个头上都包含防护装置?@Fred:是的,就是这样设置的。这也称为“循环依赖项”(以防您想搜索有关此问题的更多信息)。当我开始遇到这些问题时,我限制了一些继承。你的评论帮我弄明白了。我有Generic.h,它不是很多人继承的,到处都有。改为正向声明泛型修复了该问题。我必须仔细研究,看看还有什么可以改变的。我会支持约翰·拉科的书的推荐。任何设计C++大型系统的人都应该阅读它。