问题
I had an issue of circular references (i.e. A.h and B.h #including each other) and some people advised me to use #pragma once to prevent that. However, this solution appears to be not working still.
What's happening is that class A no longer becomes recognized in any file other than A.h (not even in A.cpp) and the same happens for class B.
Let me show you the code:
A.h
#pragma once
#include "B.h"
class A {
public: B* b;
};
B.h
#pragma once
#include "A.h"
class B {
public: A* a;
};
A.cpp
#include "stdafx.h"
#include "A.h"
#include "B.h"
B.cpp is same as A.cpp
The error trace reads as followed:
1> B.cpp 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C2143: syntax error : missing ';' before '' 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1> A.cpp 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C2143: syntax error : missing ';' before '' 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
There are two more things I'd like to clarify:
How and when to use #include "stdafx.h" in Visual Studio 2010 (I really hate this IDE, but it appears to be the only one that works well with C++ - Netbeans is total trash with this language)
How to use #pragma once correctly? I'd assume I'd just put it at the first line of each file (well, obviously that doesn't solve my problems!). Also, should it be placed before or after #include "stdafx.h"? Note: I didn't put #pragma once in stdafx.h
Thanks.
Edit: I forgot the semi-colons, thus the original error trace was bloated. Edit2: I forgot to use pointers. My actual program did use pointers instead of plain object values and I neglected that in my haste to create a small example.
回答1:
You can't have circular dependencies.
Think of it like this. If you instanciate an object of type A; then how big is it? The answer is infinitely large. So you can't create objects that are circular like that anyway.
You need to break the cycle with an optional value (a pointer).
SO If you change B to hold a pointer to A and use forward references then it works.
#pragma once
class A; // Forward reference.
class B {
public: A* a; // Break cycle with a pointer. (In real life use a smart pointer)
}
Note: You should still use the #pragma once
in your header files.
回答2:
No, #pragma once
does not solve circular dependency issue any more than standard include guard does. What you're doing is essentially a recursive structure, and you cannot have a recursive structure using plain values, as this would mean sizeof(T) == infinity
. The solution here is to:
- Not include B.h in A.h.
- Using
std::unique_ptr
(or just a raw pointer, if it doesn't own the instance) instead of plain value to holdB
instance inA
.
Or vice versa, depending on what your classes actually are. Of course the best solution is to just get rid of the circular dependency completely, at design level (refactor common parts out, that kind of stuff).
stdafx.h
is unrelated (the name is just a convention) — search for "precompiled header".
来源:https://stackoverflow.com/questions/10918250/pragma-once-and-include-issues