C++ c++;带条件编译的标头包含顺序

C++ c++;带条件编译的标头包含顺序,c++,compilation,header,C++,Compilation,Header,假设我有两个文件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.水电站: #indef DEF_B #define DEF_

假设我有两个文件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.水电站:

#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
我不想将A.hpp包含在B.hpp中(反之亦然),因为每次我需要A.hpp时,我都需要B.hpp(反之亦然)

但当我在主文件中写入:

main.cpp

#include"A.hpp"
#include"B.hpp"

int main(){
    A a;
    B b;
}
A::方法(B)
未知。如果我颠倒包含顺序,我将只有
B::method(A)

当包含两个标头时,是否有办法访问这两个方法

[编辑] 该方法也适用于没有.cpp文件的模板类。
[/edit]

我会使用转发声明,类似于:

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
#include "A.hpp"
#include "B.hpp"

void A::method(const B& b) { /* your implementation */ }
#indef DEF_B
#define DEF_B

class A; // Forward declaration of A

class B { // Definition of B
public:
    void method(const A& a);
};
#endif
#include "B.hpp"
#include "A.hpp"

void B::method(const A& a) { /* your implementation */ }
#include "A.hpp"

void foo()
{
    A a;
    // B b; // If uncommented, that would fail to compile.
}
A.cpp

#indef DEF_A
#define DEF_A

class B; // Forward declaration of B

class A { // Definition of A
public:
    void method(const B& b);
};
#endif
#include "A.hpp"
#include "B.hpp"

void A::method(const B& b) { /* your implementation */ }
#indef DEF_B
#define DEF_B

class A; // Forward declaration of A

class B { // Definition of B
public:
    void method(const A& a);
};
#endif
#include "B.hpp"
#include "A.hpp"

void B::method(const A& a) { /* your implementation */ }
#include "A.hpp"

void foo()
{
    A a;
    // B b; // If uncommented, that would fail to compile.
}
B.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
#include "A.hpp"
#include "B.hpp"

void A::method(const B& b) { /* your implementation */ }
#indef DEF_B
#define DEF_B

class A; // Forward declaration of A

class B { // Definition of B
public:
    void method(const A& a);
};
#endif
#include "B.hpp"
#include "A.hpp"

void B::method(const A& a) { /* your implementation */ }
#include "A.hpp"

void foo()
{
    A a;
    // B b; // If uncommented, that would fail to compile.
}
B.cpp

#indef DEF_A
#define DEF_A

class B; // Forward declaration of B

class A { // Definition of A
public:
    void method(const B& b);
};
#endif
#include "A.hpp"
#include "B.hpp"

void A::method(const B& b) { /* your implementation */ }
#indef DEF_B
#define DEF_B

class A; // Forward declaration of A

class B { // Definition of B
public:
    void method(const A& a);
};
#endif
#include "B.hpp"
#include "A.hpp"

void B::method(const A& a) { /* your implementation */ }
#include "A.hpp"

void foo()
{
    A a;
    // B b; // If uncommented, that would fail to compile.
}
然后在main.cpp中 当您同时使用A.hpp和B.hpp时,请将其包括在内。 但如果在C.cpp中只使用A(不使用B),则可以执行以下操作

C.cpp

#indef DEF_A
#define DEF_A

class B; // Forward declaration of B

class A { // Definition of A
public:
    void method(const B& b);
};
#endif
#include "A.hpp"
#include "B.hpp"

void A::method(const B& b) { /* your implementation */ }
#indef DEF_B
#define DEF_B

class A; // Forward declaration of A

class B { // Definition of B
public:
    void method(const A& a);
};
#endif
#include "B.hpp"
#include "A.hpp"

void B::method(const A& a) { /* your implementation */ }
#include "A.hpp"

void foo()
{
    A a;
    // B b; // If uncommented, that would fail to compile.
}
也许你应该试一试。您可以轻松地将实现细节隐藏在.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 ){}
};
//重要提示:fwd声明如Jarod42所述!
乙级;;
AImpl类;
甲级
{
空心法(B*B)
{
impl->(b);
}
AImpl*impl;//这将起作用,因为编译器不需要知道
//创建指针或指针时的精确对象大小
//引用…cpp中的类型定义
}
//B也一样;
//在A和B的cpp文件中:
类AImpl:公共模板类
{
空位法(B*B){}
};

我希望这能帮助你解决你的问题

为什么不使用前向声明(并通过常量引用传递参数)?(并在A.cpp和B.cpp中移动实现)@Jarod42如果我从未定义转发类会发生什么?对于模板类,您不能使用它的定义。(例如,你不能做
A;
。@Jarod42好吧,这看起来不错。我可以写一篇文章吗?a.一些方法()
B::method(a const&a)
?谢谢你的回答,但我看到了一些问题。。。1) 对于没有.cpp文件的模板类,此方法将不起作用。2) 我想如果我在A.cpp和B.cpp中包含这两个文件.hpp,我仍然需要提供所有文件来编译code1)For template类,您必须包含这两个文件。2)如果您希望在不同的项目之间共享文件A.cpp,而一个项目不使用
B
,您仍然可以添加一个新的define
USE_B
来有条件地包含相关部分(但不要依赖include guard
DEF_B
,它可能会根据包含顺序破坏您的代码)。