As you have explained the situation, where the parameters are passed by value (i.e. copied), you have done the normal thing. In order to write code that uses A the compiler needs to know the precise size of B, i.e. the declaration. The headers a.h and b.h should have include guards to avoid an endless loop.
If method_x1() takes a reference or pointer to an A or B, rather than the copy you showed, then you can use forward declarations to break the header file dependency:
// a.h
#ifndef A_H
#define A_H
class B; // forward declaration only
class A
{
public:
void method_A1(const B &b);
void method_A2(B *b);
};
#endif
// a.cpp
#include "a.h"
#include "b.h"
void A::method_A1(const B &b) {}
void A::method_A2(B *b) {}
// b.h
#ifndef B_H
#define B_H
class A; // forward declaration only
class B
{
public:
void method_B1(A &a);
void method_B2(const A *a);
};
#endif
// b.cpp
#include "b.h"
#include "a.h"
void B::method_B1(A &a) {}
void B::method_B2(const A *a) {}
// a.h
#ifndef A_H
#define A_H
class B; // forward declaration only
class A
{
public:
void method_A1(const B &b);
void method_A2(B *b);
};
#endif
// a.cpp
#include "a.h"
#include "b.h"
void A::method_A1(const B &b) {}
void A::method_A2(B *b) {}
// b.h
#ifndef B_H
#define B_H
class A; // forward declaration only
class B
{
public:
void method_B1(A &a);
void method_B2(const A *a);
};
#endif
// b.cpp
#include "b.h"
#include "a.h"
void B::method_B1(A &a) {}
void B::method_B2(const A *a) {}
To copy to clipboard, switch view to plain text mode
The compiler then requires only a pointer to B, of known size, to build code using A. It no longer requires the full declaration of B. The full declaration of B will be required in the implementation of A.
In large libraries with lots of inter-relationships these measures can reduce compilation time quite a bit by reducing the amount of pre-processor material to be handled.
Bookmarks