Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of forward declaration?

what is the description or meaning of this: for example:

class test;

class test
{
  .....
};
like image 728
navid Avatar asked Jun 24 '10 12:06

navid


3 Answers

C++ (like C) was designed to be implementable by a single-pass compiler. Forward references are necessary in cases where the compiler needs to know that a symbol refers to a class before the class is actually defined. The classic example of this is when two classes need to contain pointers to each other. i.e.

class B;

class A {
  B* b;
};

class B {
  A* a;
};

Without the forward reference to B, the compiler could not successfully parse the definition for A and you can't fix the problem by putting the definition of B before A.

In a language like C#, which needs a two-pass compiler, you don't need forward references

class A {
  B b;
}

class B {
  A a;
}

because the compiler's first pass simply picks up all symbol definitions. When the compiler makes its second pass, it can say "I know B is a class because I saw the definition on my first pass".

like image 134
Ferruccio Avatar answered Oct 04 '22 00:10

Ferruccio


The compiler needs the definition of a class if member/methods of that class are accessed or if the size needs to be known. In other cases, a forward declaration is sufficient. This saves you compile time. Example:

class A { 
  B m_b; 
  C* m_ptrC;
}; 

For this class, you need the definition of B (size needed) and only the declaration of C (pointers have fixed size). You only need to include the header of B, not the one of C. A forward declaration of C is sufficient.

a.h:

#ifndef A_H
#define A_H

#include <b.h>
class C;

class A
{
  B m_b;
  C* m_ptrC;
}
#endif

The forward declaration of c (instead of including c.h which is also possible) saves you parsing c.h whenever you include a.h. Across a large project, this may save a lot of compile time. Another benefit is, that changes in c.h do not trigger a recompile for a in this case. I do not know if compiler recognize this if you include c.h instead of forward declaring it.

For more information, try understanding the pimpl-idiom (just google for it. you'll get lots of hits).

Of course - in a.cpp if you actually do something with the pointer to c (e.g. m_ptrC->Add()), you'll need to include c.h. But a.cpp is read only once where the header file is read n times with large n for classes that are used very often in large projects.

Forward declaration also allows for circular dependencies. Example:

class B;

class A {
 B* m_ptrB;
}

class B {
 A* m_ptrA;
}

Just remember - you can't use any information about size & methods if you use forward declarations. This is also the case with 2 classes including each other (one class does not need the forward reference though). I personally think circular references are bad style and you should avoid them if possible.

For additional information: C++ FAQ

Thank you for the comment about the circular dependencies, I simply forgot them.

like image 32
Tobias Langner Avatar answered Oct 03 '22 22:10

Tobias Langner


First, the class is declared, then it is defined.

Declaration: It just tells the compiler: Ok, here's something (method, class, etc.), that can be used by the given name. It just binds the given name to something.

Definition: It tells the compiler: Ok, here's what (and how) the methods, classes, etc. actually do their stuff. If something is defined, then the compiler is caused to actually allocate space for it.

You might have a look at here.

like image 26
phimuemue Avatar answered Oct 03 '22 22:10

phimuemue