C++ Tip: Forward Declaration
Yesterday I managed to solve something that was bugging me for some time now in my project. I thought it couldn’t be done in C++.
While I was looking at the KDE source code, I found out about forward declaration of classes. This solved my problem of a circular dependency I was having between two of my classes. I have the following class hierarchy:
Component
|
+—Container
|
+—Window
Now, Window inherits from Container which inherits from Component. Let’s focus on the Component and Container class. Both Component and Container are abstract classes meaning that you can’t create an object of these classes. A Container is basically a Component that can hold other Components. Now Components will have Container’s as parent. So I need an instance variable of type Container inside of Component to point to the parent of a Component. But the problem was that Container was inheriting from Component, so how was I suppose to be able to use Container inside of the base class Component. The answer came from using a forward declaration.
Here was my code:
//Component.h
class Component
{
protected:
Container *parent;
…
public:
void setParent(Container &c);
…
};
//Container.h
class Container : public Component
{
protected:
…
public:
…
};
Of course the compiler complained because it didn’t recognize Container as a type, so I changed my Component.h file and added a forward declaration:
//Component.h
class Container;
class Component
{
protected:
Container *parent;
…
public:
void setParent(Container &c);
…
};
This worked. But I had another problem. I actually needed to use functions from the Container class inside of my class implementation. My class implementation looked something like this:
//Component.cpp
#include “Component.h”
…
void Component::setParent(Container &c)
{
c.add(*this); //Some function from the Container class.
}
But the compiler complained because Container wasn’t defined. It was declared, but not defined (those are very different). So to fix this, I included the Container header in the Component implementation file:
//Component.cpp
#include “Component.h”
#include “Container.h”
…
void Component::setParent(Container &c)
{
c.add(*this); //Some function from the Container class.
}
The compiler didn’t complain. It compiled, no warnings. The code worked. So that’s how you can resolved dependency between classes even if one of the class is a base class and the other is the derived class.
Great explanation; this is usually the point where
eyes glaze over when someone is learning C++; it certainly was for me.
BTW, love your posts about Haiti. Brings back good memories.
Like many people, inside foo.cpp I make a habit of including only foo.h.
However, your solution is so simple, and what it does is so clear, we now have the “Marv rule” in our style guidelines.
Complete obviousness is what makes a great tip great. Thanks a lot.
Nice explanation, but some compilers give you an compile time ‘class’ type redefinition error if you include “Container.h” and if container.h contains Component.h (recursive inclusion). So the solution is to add #pragma once at the beginning of the header files.