Contents |
Imagine a spaceship with a weapon, where the weapon is a separate class, and the weapon must know its owner:
class Ship {
Weapon &weapon;
};
class Weapon {
Ship &owner;
};
This does not work, as the Weapon class is undefined when defining class Ship. The remedy is a forward declaration:
class Weapon; // forward definition
class Ship {
...
The above approach can get very tricky in larger class hierarchies.
Imagine the example split into files, ship.h:
#pragma once
#include "weapon.h"
class Weapon; // forward declaration
class Ship {
public:
Ship() : weapon(0) {}
void fire() { weapon->fire(); } // Error: we are *not* allowed to use
// methods of the undefined class.
Weapon *weapon; // We may have a pointer to an undefined
}; // class, but not a reference.
weapon.h:
#pragma once
#include "ship.h"
class Ship; // forward declaration
class Weapon {
public:
Weapon(Ship &owner) : owner(owner), fired(0) {}
void fire() { fired++; }
Ship &owner;
int fired;
};
and main.cpp:
#include "weapon.h"
#include "ship.h"
int main(void) {
Ship R9a;
Weapon laser(R9a);
R9a.weapon = &laser;
}
Note that although we would like to initialize the Ship with a Weapon reference, it is impossible to retain the initialization of the Weapon class with the Ship reference. We cannot have both. Therefore, we opt to use a weapon pointer which is set after creating both the Ship and the Weapon. If we forget to set it, the program will fail, so it should be changed to something similar to:
void fire() { if(weapon) weapon->fire(); }
However, the above example doesn't even compile. The problem is that Ship::fire() uses Weapon::fire() before Weapon is defined. We may not access members of an as yet undefined class.
The solution is unsatisfying: we cannot retain Ship::fire() as an inline member function. We have to edit ship.h:
...
class Ship {
public:
Ship() : weapon(0) {}
void fire(); // May not be inline, as it accesses
// a weapon member.
Weapon *weapon;
};
add put the Ship::fire() implementation in a separate translation unit (ship.cpp file):
#include "ship.h"
void Ship::fire() { weapon->fire(); }
.cpp file).