tags:

views:

97

answers:

9

Hi,

Is some one able to explain why header files have something like this?

class foo; // This here?
class bar
{
   bar();

};

Do you need an include statement when using this?

Thanks.

+2  A: 

That's a forward declaration. You need it for example if class bar has a pointer to a foo object, but you don't want to include the whole definition of the foo object immediately.

Jesper
A: 

That's a forward declaration. Consider the following example:

class foo; // you likely need this for the code beneath to compile
class bar {
    void smth( foo& );
};

If you haven't included the definition of class foo in such a way that the compiler sees it before compiling the definition of class bar the code will not compile (the compiler will say it doesn't know what foo means) unless you have the forward declaration.

sharptooth
A definition is not necessary. A declaration suffices. Your example shows a declaration of foo.
sellibitze
+1  A: 

this is a forward declaration of the class. In my experience, this is typically done when you have a circular dependency.. for example

in foo.h
--------
#include "bar.h"

class foo
{
public:
    foo(bar *bar);
private:
    foo *m_foo;
};

and in bar.h
------------
class foo;
class bar
{
public:
    void methodFooWillCall();
protected:
    std::list<foo *> myFoos;
}
aschepis
A: 

It's a forwards declaration of the class 'foo'. It allows you to declare pointers and references to the class, but not use it (eg. call members or determine its size), because it's not yet defined! It must later be followed up with a full, normal declaration (class foo { ... };).

It's useful for things like declaring two classes which hold pointers to each other, which otherwise would be impossible to set up.

AshleysBrain
what you call "normal declaration" is a definition
sellibitze
+7  A: 

The first class foo; is called a forward declaration of the class foo. It simply lets the compiler know that it exists and that it names a class. This makes foo what is called an "incomplete type" (unless the full declaration of foo has already been seen). With an incomplete type, you can declare pointers of that type, but you cannot allocate instances of that type or do anything that requires knowing its size or members.

Such forward declarations are frequently used when two types each may have pointers to each other, in which case both need to be able to express the notion of a pointer to the other type, and so you would have a circular dependency without such a thing. This is needed mostly because C++ uses a single pass mechanism for resolving types; in Java, you can have circular dependencies without forward declarations, because Java uses multiple passes. You may also see forward declarations where the author is under the misguided impression that using forward declarations instead of including the required header reduces compile time; that, of course, is not the case, because you need to include the full declaration (i.e. the header), anyway, and if preprocessor guards are used, then there is basically no difference in compile time.

To answer your question on whether you need the include or not... assuming you only need a partial type, then your header does not need to directly include the header for the type that has been forward declared; however, whoever makes use of your header, when they use your type will need to include the header for the forward declared type, and so you might as well just include the other header.

Michael Aaron Safyan
+1. Some minor nit: what you call "full declaration" is actually a "definition".
sellibitze
A: 

This is called forward declaration. The body of the class foo would be defined at a later part of the file. Forward declaration is done to get around cyclic dependencies: The definition of class Bar requires class Foo and vice versa.

class Bar
{
   Foo * foo;
};
class Foo
{
   Bar * bar;
};

As you can see, Bar has a reference to Foo and vice versa. If you try to compile this, the compiler will complaint saying that it doesn't know anything about Foo. The solution is to forward declare the class Foo above the Bar (just like you declare the prototype of a function above the main and define its body later).

class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
   Foo * foo;
};
class Foo
{
   Bar * bar;
};
Amarghosh
A: 

This is called a forward declaration. It is used to make your code aware that the class foo exists. This in turn can be used by the class bar.

It's commonly used to solve circular includes problems. Take this for example

//a.h
#include "b.h"

class A
{
    void useB(B obj);
}

and

// b.h
#include "a.h"
class B
{
     void useA(A obj);
}

This causes a circular include problem, because a.h includes b.h which in turns includes a.h, to infinity. You can solve this problem by making a forward declaration of each class in each header, like so :

//a.h
class B;

class A
{
    void useB(B obj);
}

// b.h
class A;

class B
{
     void useA(A obj);
}

Note : Very often when you have a circular include problem, this is indicative of a conception/modelling problem. You should probably ask yourself if your classes are well defined before trying to solve your problem with forward declarations.

raph.amiard
+1  A: 

Just curious, why do we need the term forward declaration at all? Isn't a forward declaration simply a declaration (as opposed to a definition)?

class X;  // declaration

class X   // definition
{
    int member;
    void function();
};
FredOverflow
+1. Yes it is. :-)
sellibitze
A: 

Try to think of writing this:

file bar.h:

        #include "bar.h"

        class Foo
        {
        Bar* bar_ptr;
        }

file foo.h:

        #include "foo.h"

        class Bar
        {
            Foo* foo_ptr;
        }

This won't work, first due to infinite #include chain, then if you get rid of one of the includes, either Foo won't know what Bar is, or Bar won't know what Foo is.

Try this instead:

        class Bar;

        class Foo
        {
        Bar* bar_ptr;
        };

file foo.h:

        class Foo;

        class Bar
        {
            Foo* foo_ptr;
        };
SF.