Sunday, 1 June, 2008

Forward Declarations

We can use forward declaration to speedup the compilation and to reduce the interdependencies between different modules.

Consider following CServer and CClient classes, declared in Server.h and Client.h header files respectively.

Server.h

#include "Client.h"

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient &clnt);

private:
CClient *m_ptrClient;
};

In this case it will always be more efficient to omit the inclusion of the header file Client.h, instead we can use forward declaration as shown below,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient &clnt);

private:
CClient *m_ptrClient;
};

This is sufficient in this case because of the reason that C++ compiler is optimized enough and it doesn't need to know about the size and interfaces of the class CClient within the declaration of the CServer class.

However we have to include the Client.h header in Server.cpp where the actual definition of the member functions exist.

Below are some use cases which indicates the usage of forward declarations,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt); // non-ref/pointer parameter

private:
CClient *m_ptrClient;
};

Usage of forward declaration is valid even though we have non-reference or non-pointer parameter in the member function.

Below is a case where we cannot use forward declaration,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt) { clnt.updateMsg(); } // inline definition

private:
CClient *m_ptrClient;
};

Cannot use forward declaration here because SendMsg has it's inline definition which is actually using CClient::updateMsg(). In this case we need to include the header Client.h within Server.h

One more case where we can not use forward declaration,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt);

private:
CClient m_client;
};

Since the member variable m_client within CServer is of type CClient, compiler need to know about the CClient. We cannot use the forward declaration here.

The cause of compilation speed increase

The increase in speed by forward declaration is due to the fact that header files can be included multiple times, whereas implementation files (CPP) are not. Therefore, keep the heaer files as simple as possible.

Rule of Thumb : "If the compiler doesn't need it, you won't have to do it." C++ is well optimized.