// PhysicalTraits.h
struct PhysicalTraits {
unsigned int age; // years
double height; // meters
PhysicalTraits(const double H = 0.0, const unsigned int A = 0u) : age (A), height(H) {};
~PhysicalTraits() {};
};
// People.h
#include <PhysicalTraits.h>
class People {
PhysicalTraits traits;
public:
People(const double H = 0.0, const double A = 0u) : traits(H, A);
~People() {};
void displayAge() { std::cout << "You are " << traits.age << " years old." << std::endl; }
void displayHeight() { std::cout << "You are " << traits.height << " meters tall." << std::endl; }
};
// Me.h
#include <PhysicalTraits.h>
class Me {
PhysicalTraits traits;
public:
Me(const double H = 0.0) : traits(H);
~Me() {};
void displayAge() {
// I want `traits.age` to throw an error
std::cout << "You are " << traits.age << " years old." <<
}
void displayHeight() {
std::cout << "You are " << traits.height << " meters tall." << std::endl;
}
};
I intend to allow objects of type People
to access traits.age
. However, I don't want to know my age, so I want to restrict objects of type Me
from accessing traits.age
.
To do this, I modified PhysicalTraits.h
:
#include <People.h>
struct PhysicalTraits {
double height; // meters
private:
unsigned int age; // years
friend class People; // Objects of type `People` can access age
};
With age
as a private member variable and as a friend with People
, but not Me
. I've solved the problem... kind of.
However, the new problem is that I've included People.h
in PhysicalTraits.h
and PhysicalTraits.h
in People.h
. So, when PhysicalTraits.h
is compiled, before defining the PhysicalTraits
object it will jump to the definition of the People
object, which requires that the PhysicalTraits
object is defined.
How can I avoid this "mutual-include" problem while still ensuring that an object of type Me
cannot access traits.age
?
You don't have to include People.h
in PhysicalTraits.h
. Full definition of class People
is not required there. You can just declare that class.
PhysicalTraits.h
would look like that:
class People; // Forward declaration
struct PhysicalTraits {
double height; // meters
private:
unsigned int age; // years
friend class People; // Objects of type `People` can access age
};
Forward declarations was created exactly in order to solve problems like yours (mutual-include). In c++ you code is (in general) parsed from top to bottom which creates a lot of problems when you need to use e.g. function which is defined after the call. Thats why declaration was implemented. In your case compiler need to know only the name of the class, so declaration will suffice. However, you cannot create object of class which is only declared or call any of its methods.
It's also noteworthy that using declaration everywhere where it is possible speeds up the compilation because parsing a definition obviously takes some time.