将头文件(.h)放在另一个文件(.h或.cpp)的开头和结尾之间的区别

时间:2012-11-14 09:49:56

标签: c++

最近,我在mac os上编译libfacebookcpp。我发现了一个我无法理解的奇怪用法。 有两个文件,AuthorizedObject.hpp和List.hpp。 在文件AuthorizedObject.hpp的末尾,有一行:#include“List.hpp”。现在我编译成功。但 当我将该行移动到开头时,会发生错误。代码的骨架是:

//AuthorizedObject.hpp
class AuthorizedObject
{
public:
... 
template<class TType>
void _GetConnection(const ::std::string& uri, List<TType> *list) const
{
    LIBFACEBOOKCPP_CHKARG(list);

    Json::Value value;
    request_->GetResponse(uri, &value);

    list->Deserialize(*this, value);
}
...
}
#include "List.hpp" //end

----------------------------------------------------------
//List.hpp 
#include "AuthorizedObject.hpp"
class LIBFACEBOOKCPP_API List : public AuthorizedObject
{
private: // private classes
...
}

我想如果将该行(#include“List.h”)放在AuthorizedObject.hpp的开头,则这两个文件按圆圈互相包含。所以编译器不知道怎么编译。但是把那行放到最后会解决这个问题吗?为什么?提前谢谢。

2 个答案:

答案 0 :(得分:1)

不同之处在于定义了类/函数/ ...的顺序,例如:

#include "one.h"
void foo(bar &);

// Will result into:
class bar {};
void foo(bar&);

哪个是有效代码。另一方面:

void foo(bar &);
#include "one.h"

// Will result into statements in different order:
void foo(bar&);
class bar {};

这意味着在声明之前使用class bar,因此出错。您还可能需要确保不会处理两次声明(UmNyobe already covered that partially):

#if !defined( MY_HEADER_INCLUDED_)
# define MY_HEADER_INCLUDED_
// Complete content goes here
#endif /* !defined( MY_HEADER_INCLUDED_) */

这样,当您第一次包含文件时,将不会定义MY_HEADER_INCLUDED_(内容将被“放置”在代码中)。第二次(您将其包含在圆圈中)将定义MY_HEADER_INCLUDED_,因此将跳过完整的正文。

答案 1 :(得分:1)

你是对的,这就是问题所在。你错了,编译器不知道如何编译 - 它确实如此,你只是错误地使用它:)。

AuthorizedObject.hpp开头的包含警卫(我假设它包含警卫或#pragma once指令)将定义AUTHORIZED_OBJECT_H(或类似)。之后,您加入List.h,其中又包含标题AuthorizedObject.hpp。由于已经定义了包含保护宏,因此跳过AuthorizedObject的定义,因此List不知道类型,但是使用它,因此您会收到错误。

如果你在最后移动了include,那么编译器已经处理了AuthorizedObject的定义,因此在List.h中使用它是有效的。