Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: C++
Expertise: Beginner
May 1, 1997

C++ Classes

Question:
I have written a program with two classes. Each uses the other within it and contains pointers to the other. However, this means that the first class encountered by the compiler has no previous class to use, so I get errors. How can I overcome this?

Answer:
This problem is known as circular referencing. There are different solutions depending on how your code is structured.

First let's assume that both class declarations are in the same header file (.h). For example, lets say we have classes Master and Dog. Master references Dog and Dog references Master, but it will not be possible for one or the other depending the order of the class declarations. So, how could you declare the Master class first; for instance, one that contains a reference to a Dog class that has yet to be recognized by the compiler. In this case you would add a forward declaration for the Dog class prior to declaring the Master class. This will indicate to the compiler that the Dog class declaration will follow eventually, but prior to it being explicitly utilized in the implementation of the Master class (see code = extract below).

// MasterAndDog.h

// Forward class declaration of Dog
class Dog;

// Master class declaration
class Master{

// Operations
public:
	void Contact(Dog* pDog);
	void SendCommand(const char* cmd);

// Attributes
private:
	Dog* m_pDog;
};

// Dog class declaration
class Dog{

// Operations
public:
	void Contact(Master* pMaster);
	void AskForAttention( );

// Attributes
private:
	Master* m_pMaster;
};
A more typical C++ application will have a separate header file and methods file for each class defined. In that case you could do something similar to above with a few enhancements. Since the class declarations are in different header files, you would have to include forward declarations of the other class in both header files, and include the header files of the forward declared class to each method's file, similar to the following:
// Master.h

// Forward class declaration of Dog
class Dog;

// Master class declaration
class Master{
...
}

// Master.cpp
#include "Master.h"
#include "Dog.h"

/* Master class definition follows... */

****************************************************************

// dog.h

// Forward class declaration of Master
class Master;

// Dog class declaration
class Dog{
...
}

// Dog.cpp
#include "Dog.h"
#include "Master.h"

/* Dog class definition follows... */
Another alternative for this scenario is to simply remove the forward declarations from the header file and include the header file of the other class to this header file. Therefore there is no need to include the header files of the other class to methods files. For example:
// Master.h

#include "dog.h"  // Dog class

// Master class declaration
class Master{
...
}

// Master.cpp
#include "Master.h"

/* Master class definition follows... */

****************************************************************

// dog.h

#include "master.h"

// Dog class declaration
class Dog{
...
}

// Dog.cpp
#include "Dog.h"

/* Dog class definition follows... */
However, I don't recommend this approach, because even if you have an incremental compiler, both Master and Dog source files will recompile if you change the class declaration in one or the other. All the compiler does is determine that the interface of a class has changed; therefore, any other class header that includes the header of the class interface that changed should be recompiled also to ensure a continued functioning application. Hence you have an unnecessary ripple effect.

The best solution is to avoid circular referencing altogether by decoupling the classes from one another, and incorporate a Mediator class through which all other classes interact by letting the Mediator class determine the effects that should happen to other classes involved. The end result is that you can easily extend or revamp parts of your system infrastructure without being severely limited by interdependencies.

DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date