#pragma once and #include issues

风格不统一 提交于 2020-01-17 10:20:17

问题


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:

  1. 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)

  2. 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:

  1. Not include B.h in A.h.
  2. Using std::unique_ptr (or just a raw pointer, if it doesn't own the instance) instead of plain value to hold B instance in A.

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!