Dear friends:
I have the following two classes.

#ifndef EQUATION_H
#define EQUATION_H

#include <stdlib.h>
#include <map>

class Mesh;

class Equation {
public:
  Equation();
  virtual ~Equation(){};

  void associateMesh(Mesh * _pMesh){ pMesh = _pMesh;};
 
  virtual void addsItsVariables4PostProcessing(map<string,const Variable*> & variablesMap)=0;

protected:
  string name;          
  const Mesh* pMesh; };

#endif

Before the class Equation, there are a pre declare of class mesh. I do not understand why not to use a include to include the head file of Mesh class, what is the difference.
In the class member function "addsItsVariables", it use a paramter "map<string,const Variable*>" which is not the class member, is this illegal?
Regards

Edited 5 Years Ago by ztdep: n/a

It is better to include *.h files in *.c files. You can faced with message "Mesh class has already defined". To avoid id you says that class Mesh will be defined but in Equation you need it right now.

As fas As I know you also can use in Mesh.h file
#ifndef _MESH_H
#define _MESH_H
class Mesh{
....
#endif

and then include in all *.h files you need.

This "pre-declared class", as you call it, is what programmers call a "forward-declaration". A forward-declaration is useful when you need two classes to depend on each other (which would otherwise not be possible). Here is a simple example:

struct DogOwner {
  Dog fido;
};

struct Dog {
  DogOwner master;
};

Obviously, the above won't work because to declare DogOwner, you need Dog to be declared, but to declare Dog, you need DogOwner to be declared. This is called circular referencing (like circular logic), it simply cannot work that way. Forward-declarations offer a solution to this, as follows:

struct DogOwner; //forward-declare DogOwner

struct Dog {
  DogOwner* master; //note that a forward-declared class can only be held by pointer or reference.
};

struct DogOwner {
  Dog fido;  //this works!
};

What a forward-declaration does is simply to give a promise to the compiler that there will be a real declaration of that class later on in the source code. This way, you can declare pointer and references to objects of that class before the compiler actually sees the declaration of that class (but, you cannot use objects of that class, only references and pointers).

So, the reason why you have this forward-declaration of Mesh in the code you posted is most likely because Mesh also needs the declaration of Equation.

Additional note: most of the time forward-declarations are avoidable and are often an indication of poor design of the software. So, be cautious in using them, explore other options before, it is likely that you will find a nicer solution that doesn't require a forward-declaration.

Forward declarations are really useful for helping to remove build dependencies that can lead to excessive compilation times. For that reason, I would tend to favour forward-declaration over actually including the header file if possible.

I would want to avoid a cyclic dependency as mike_2000_17 explained though, so weirdly I would say that they're correctly used when you don't need to use them (i.e. if it's possible to use the header file, but you don't want the long build times).

Comments
good point

@ravenous, I totally agree. The need for a forward-declaration (from having circular dependencies) is usually indicative of some fundamental design flaw (i.e. not splitting responsibilities correctly leads to awkward dependencies, circular dependencies and/or too many dependencies). But you are right, aside from the purpose of resolving circular referencing problems, forward-declarations can be very useful to minimize the trail of header-file inclusions and thus reducing build times. Similarly, the Cheshire Cat idiom (or PImpl) uses forward-declarations to tuck away a dependency relating to the details of an implementation into the cpp, and thus, achieving a compilation firewall which is also very useful to minimize the needs for recompilation of source code.

This "pre-declared class", as you call it, is what programmers call a "forward-declaration". A forward-declaration is useful when you need two classes to depend on each other (which would otherwise not be possible). Here is a simple example:

struct DogOwner {
  Dog fido;
};

struct Dog {
  DogOwner master;
};

Obviously, the above won't work because to declare DogOwner, you need Dog to be declared, but to declare Dog, you need DogOwner to be declared. This is called circular referencing (like circular logic), it simply cannot work that way. Forward-declarations offer a solution to this, as follows:

struct DogOwner; //forward-declare DogOwner

struct Dog {
  DogOwner* master; //note that a forward-declared class can only be held by pointer or reference.
};

struct DogOwner {
  Dog fido;  //this works!
};

What a forward-declaration does is simply to give a promise to the compiler that there will be a real declaration of that class later on in the source code. This way, you can declare pointer and references to objects of that class before the compiler actually sees the declaration of that class (but, you cannot use objects of that class, only references and pointers).

So, the reason why you have this forward-declaration of Mesh in the code you posted is most likely because Mesh also needs the declaration of Equation.

Additional note: most of the time forward-declarations are avoidable and are often an indication of poor design of the software. So, be cautious in using them, explore other options before, it is likely that you will find a nicer solution that doesn't require a forward-declaration.

Dear Mike:
Thank you very much for you feedback. Now i find some new problem about it. Your examples is very good, but if we declare the two structes in two different head file. how to use the forward-declaration.

This article has been dead for over six months. Start a new discussion instead.