問題描述
我是 C++ 新手,但我無法在網上找到這個(很可能是微不足道的)問題的答案.我在編譯一些包含兩個類的代碼時遇到了一些麻煩.首先,我的#include 語句應該放在宏的內部還是外部?在實踐中,這似乎無關緊要.但是,在這種特殊情況下,我遇到了麻煩.將#include 語句放在宏之外會導致編譯器遞歸并給我#include 嵌套太深"錯誤.這對我來說似乎很有意義,因為在調用 #include 之前這兩個類都沒有被完全定義.然而,奇怪的是,當我嘗試將它們放入其中時,我無法聲明其中一個類的類型,因為它不被識別.本質上,這就是我要編譯的內容:
I'm a C++ newbie, but I wasn't able to find the answer to this (most likely trivial) question online. I am having some trouble compiling some code where two classes include each other. To begin, should my #include statements go inside or outside of my macros? In practice, this hasn't seemed to matter. However, in this particular case, I am having trouble. Putting the #include statements outside of the macros causes the compiler to recurse and gives me "#include nested too deeply" errors. This seems to makes sense to me since neither class has been fully defined before #include has been invoked. However, strangely, when I try to put them inside, I am unable to declare a type of one of the classes, for it is not recognized. Here is, in essence, what I'm trying to compile:
啊
#ifndef A_H_
#define A_H_
#include "B.h"
class A
{
private:
B b;
public:
A() : b(*this) {}
};
#endif /*A_H_*/
B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class B
{
private:
A& a;
public:
B(A& a) : a(a) {}
};
#endif /*B_H_*/
main.cpp
#include "A.h"
int main()
{
A a;
}
如果有區別,我使用的是 g++ 4.3.2.
If it makes a difference, I am using g++ 4.3.2.
為了清楚起見,一般來說,#include 語句應該放在哪里?我一直看到它們在宏之外,但我清楚地描述的場景似乎打破了這個原則.提前感謝任何幫助者!如果我犯了任何愚蠢的錯誤,請允許我澄清我的意圖!
And just to be clear, in general, where should #include statements go? I have always seen them go outside of the macros, but the scenario I described clearly seems to break this principle. Thanks to any helpers in advance! Please allow me to clarify my intent if I have made any silly mistakes!
推薦答案
我認為宏"是指 #ifndef 包含守衛?如果是這樣,#includes 絕對應該進入.這是包含守衛存在的主要原因之一,否則您很容易像您注意到的那樣以無限遞歸結束.
By "the macros" I assume you mean the #ifndef include guards? If so, #includes should definitely go inside. This is one of the major reasons why include guards exists, because otherwise you easily end up with an infinite recursion as you noticed.
無論如何,問題是當你使用A和B類(在另一個類中)時,它們還沒有被聲明.看看處理完#includes 之后的代碼是什么樣子的:
Anyway, the problem is that at the time you use the A and B classes (inside the other class), they have not yet been declared. Look at what the code looks like after the #includes have been processed:
//#include "A.h" start
#ifndef A_H_
#define A_H_
//#include "B.h" start
#ifndef B_H_
#define B_H_
//#include "A.h" start
#ifndef A_H_ // A_H_ is already defined, so the contents of the file are skipped at this point
#endif /*A_H_*/
//#include "A.h" end
class B
{
private:
A& a;
public:
B(A& a) : a(a) {}
};
#endif /*B_H_*/
//#include "B.h" end
class A
{
private:
B b;
public:
A() : b(*this) {}
};
#endif /*A_H_*/
//#include "A.h" end
int main()
{
A a;
}
現在閱讀代碼.B 是編譯器遇到的第一個類,它包含一個 A&
成員.什么是A
?編譯器還沒有遇到 A
的任何定義,所以它會發出錯誤.
Now read the code. B is the first class the compiler encounters, and it includes an A&
member. What is A
? The compiler hasn't encountered any definition of A
yet, so it issues an error.
解決辦法是對A做一個前向聲明,在B的定義之前的某個點,添加一行class A;
The solution is to make a forward declaration of A. At some point before the definition of B, add a line class A;
這為編譯器提供了必要的信息,即 A 是一個類.我們對此一無所知,但由于 B 只需要包含對它的引用,這就足夠了.在 A 的定義中,我們需要一個 B 類型的成員(不是引用),所以這里 B 的整個定義必須是可見的.幸運的是.
This gives the compiler the necessary information, that A is a class. We don't know anything else about it yet, but since B only needs to include a reference to it, this is good enough. In the definition of A, we need a member of type B (not a reference), so here the entire definition of B has to be visible. Which it is, luckily.
這篇關于C++ 中相互包含的頭文件的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!