954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

pre declare of class

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" which is not the class member, is this illegal?
Regards

ztdep
Junior Poster in Training
63 posts since Mar 2011
Reputation Points: 6
Solved Threads: 2
 

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.

assanya
Newbie Poster
2 posts since Jun 2011
Reputation Points: 11
Solved Threads: 1
 

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.

mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

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).

ravenous
Posting Pro
516 posts since Jul 2005
Reputation Points: 269
Solved Threads: 92
 

@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.

mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

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.

ztdep
Junior Poster in Training
63 posts since Mar 2011
Reputation Points: 6
Solved Threads: 2
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You