5

为什么要将包含的类声明为头文件?

#include "TreeCallObj.h"
#include "TreeDevObj.h"
#include "TreeDevCallObj.h"

class TreeCallObj; //what is the purpose of this line ?
class TreeDevObj;  //what is the purpose of this line ?
class TreeDevCallObj;  //what is the purpose of this line ?


class Apple
{
public:
...
private:
...
}
4

8 回答 8

6

考虑一下:

//a.h
#ifndef A_H
#define A_H

#include "b.h"
class A
{
   B* b;
};
#endif

//b.h
#ifndef B_H
#define B_H

#include "a.h"
class B
{
   A* a;
};
#endif

现在,您尝试将其中一个文件包含在另一个文件中,例如#include "a.h".

编译器会将其解析为:

#ifndef A_H
#define A_H

很好 -A_H没有定义

#include "b.h"

尝试粘贴内容:

#ifndef B_H
#define B_H

好的,因为B_H没有定义

#include "a.h"

这不会定义A,因为A_H已定义。所以接下来,我们有

class B
{
   A* a;
};

这将导致错误,因为A在使用之前没有定义或声明。

前向声明解决了这个问题。

当然,最好的解决方案是根本不包括(除非你绝对必须)。

于 2012-09-06T15:29:54.713 回答
5

这条线的目的是什么?

理想情况下什么都没有。这是多余的。

但是,正如@Luchian Grigore 指出的那样,可能存在设计不良的代码,以至于由于包含防护和交叉包含的不正确使用,前向声明可能是必要的。

于 2012-09-06T15:24:28.327 回答
3

如果在文件中有类的定义,那么forward declaration在正常情况下是不必要的。

于 2012-09-06T15:23:32.090 回答
1

我注意到您的标题没有防止多重包含。也有可能一些包含的其他标题(标题通常有这样的保护)包括那个标题。结果它没有编译。所以有人添加了前向声明来修复错误的错误。

于 2012-09-06T15:33:17.053 回答
1

完全没有理由。根据情况,您需要做其中之一,但不能两者都做。

于 2012-09-06T15:24:32.423 回答
1

就目前而言,没有必要。

然而,这可能是历史演变而来的:在某些时候,一个不完整的类型可能就足够了:

class Foo;

struct Gizmo
{
    void f(Foo);
};

然后,稍后,作者决定她需要完整的类型:

#include "Foo.hpp"

class Foo;

struct Gizmo
{
    void f(Foo);
    Foo x;
};

原始代码可能刚刚被修改为现在需要的标题包含......

于 2012-09-06T15:28:29.313 回答
1

我想这有一些历史。最初,编码器尝试不包含头文件,而是使用前向声明。然后随着代码的扩展,他们发现他们毕竟需要头文件,但并没有费心去删除前向声明。

正如其他人所说,在类声明之后进行前向声明是没有意义的。

于 2012-09-06T15:29:00.953 回答
0

如果您的头文件是正确的,我认为声明没有意义,因为它们应该已经在头文件中声明

于 2012-09-06T15:28:12.903 回答