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

Why declare the class that you included as a header file?

本文关键字:声明 文件 包含 为什么      更新时间:2023-10-16

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

#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:
...
}

考虑一下:

//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在使用之前没有定义或声明。

forward声明解决了这个问题。

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

这条线的用途是什么?

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

然而,正如@Luchian Grigore所指出的,可能有一个设计糟糕的代码,由于include guard和cross-include的使用不正确,可能需要进行正向声明。

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

没有任何原因。你需要根据情况做其中一个,但不能两者都做。

就目前情况来看,没有必要。

然而,这可能是历史上的演变:在某种程度上,一个不完整的类型可能已经足够了:

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

然后,在后来的一点上,作者决定她需要完整的类型:

#include "Foo.hpp"
class Foo;
struct Gizmo
{
    void f(Foo);
    Foo x;
};

原始代码可能刚刚被修改,现在需要包含标题。。。

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

正如其他人所说,在类声明之后有一个转发声明是没有意义的。

我注意到您的标头没有防止多重包含的保护。也有可能包含的一些其他标头(标头通常有这样的保护)将该标头包含在后面。结果它没有编译。因此,有人添加了前向声明来修复错误的错误。

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