带有条件编译的 c++ 标头包含顺序
Posted
技术标签:
【中文标题】带有条件编译的 c++ 标头包含顺序【英文标题】:c++ header inclusion order with conditional compilation 【发布时间】:2014-07-03 06:54:58 【问题描述】:假设我有两个文件 A.hpp 和 B.hpp
A.hpp:
#indef DEF_A
#define DEF_A
class A
/*implementation of class A*/
/*some part of it needs B*/
#ifdef DEF_B
void method(B b)/*do something with B*/
#endif
#endif
B.hpp:
#indef DEF_B
#define DEF_B
class B
/*implementation of class B*/
/*some part of it needs A*/
#ifdef DEF_A
void method(A a)/*do something with A*/
#endif
#endif
我不想在 B.hpp 中包含 A.hpp(反之亦然),因为每次我需要 A.hpp 时,我都需要 B.hpp(反之亦然)。
但是当我在主文件中写:
main.cpp
#include"A.hpp"
#include"B.hpp"
int main()
A a;
B b;
A::method(B b)
未知。如果我颠倒包含顺序,我将只有B::method(A a)
。
当包含两个标头时,有没有办法同时访问这两种方法?
[编辑] 该方法也适用于没有 .cpp 文件的模板类。 [/编辑]
【问题讨论】:
为什么不使用前向声明(并通过 const 引用传递参数)? (并在 A.cpp 和 B.cpp 中移动实现) @Jarod42 如果我从不定义转发类会发生什么?和模板类? 你不能使用它的定义。 (例如,您不能使用A a;
)。
@Jarod42 好的,看起来不错。我可以写a.some_method()
B::method(A const& a)
吗?
【参考方案1】:
我会使用前向声明,例如:
A.hpp
#indef DEF_A
#define DEF_A
class B; // Forward declaration of B
class A // Definition of A
public:
void method(const B& b);
;
#endif
A.cpp
#include "A.hpp"
#include "B.hpp"
void A::method(const B& b) /* your implementation */
B.hpp
#indef DEF_B
#define DEF_B
class A; // Forward declaration of A
class B // Definition of B
public:
void method(const A& a);
;
#endif
B.cpp
#include "B.hpp"
#include "A.hpp"
void B::method(const A& a) /* your implementation */
然后在 main.cpp 您同时使用 A.hpp 和 B.hpp 两者。 但是如果在 C.cpp 中你只使用 A(没有 B)你可以这样做
C.cpp
#include "A.hpp"
void foo()
A a;
// B b; // If uncommented, that would fail to compile.
【讨论】:
感谢您的回答,但我看到一些问题/问题... 1) 对于没有 .cpp 文件的模板类,此方法不起作用。 2)我猜如果我在A.cpp和B.cpp中包含两个文件.hpp,我仍然需要提供所有文件来编译代码 1) 对于模板类,您必须包含两个文件。 2) 如果您想在不同项目之间共享文件 A.cpp 而一个项目不使用B
,您仍然可以添加一个新定义USE_B
以有条件地包含相关部分(但不要依赖包含守卫DEF_B
,这可能会根据包含顺序破坏您的代码。【参考方案2】:
也许你应该试试pimpl-idiom。您可以轻松地在 .cpp 文件中隐藏实现细节,即使它是关于模板类的:
//Important: fwd declaration as Jarod42 already stated!
class B;
class AImpl;
class A
void aMethod( B* b )
impl->( b );
AImpl* impl; //this will work because compiler need not to know
//exact object size as we are creating a pointer or
//reference...type definition in cpp
// same here for B;
//in cpp file of A and B:
class AImpl : public TemplateClass<X>
void aMethod( B* b )
;
希望对您的问题有所帮助!
【讨论】:
以上是关于带有条件编译的 c++ 标头包含顺序的主要内容,如果未能解决你的问题,请参考以下文章
C++:当包含从类模板派生的类的标头时,编译器警告 C4505