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.


2 comments:

ppp said...

hey Prashi nice Article's man....
i was actually looking for somthing
like creation of shared library(.so) soo i just found your link somewhere, currently i am working on C & Linux.
hey this is my ID:
pramodmgowda@gmail.com add me to your gtalk

Anonymous said...

Thank you very much.
That was very useful. In fact I have been coding C++ for a long time. I had used forward declaration for classes that need circular referencing.
But I had never encountered the case in which one needs to access members of the Forward-Declared object.
You helped me a lot.