gcc: cross-referencing class compilation

162 Views Asked by At

if got a quite simple question (at least I hope so), but I cannot figure out what to do to tell g++ in what order to "complete" my classes. I reduced it to this simple example:

base.h:

#ifndef BASE_H_
#define BASE_H_

#include "otherclass.h"
class otherclass;

class base {
    public:
        base(otherclass* other);

    protected:
        otherclass* m_other;
};

#endif /* BASE_H_ */

derived.h:

#ifndef DERIVED_H_
#define DERIVED_H_

#include "base.h"

class derived : public base {
    public:
        derived(otherclass* other);
};

#endif /* DERIVED_H_ */

(both corresponding .cpp files only contain constructors which assign the given otherclass* to the member variables)

otherclass.h:

#ifndef OTHERCLASS_H_
#define OTHERCLASS_H_

#include "derived.h"

class otherclass {
    public:
        otherclass( );

    protected:
        derived* m_derived;
};

#endif /* OTHERCLASS_H_ */

otherclass.cpp:

#include "otherclass.h"

otherclass::otherclass() {
    m_derived = new derived(this);
}

Since it may be relevant I'll paste the entire output of scons:

g++ -o base.o -c base.cpp
g++ -o derived.o -c derived.cpp
In file included from otherclass.h:4:0,
             from base.h:4,
             from base.cpp:1:
derived.h:8:29: error: expected class-name before '{' token
g++ -o main.o -c main.cpp
In file included from base.h:4:0,
             from derived.h:4,
             from derived.cpp:1:
otherclass.h:11:3: error: 'derived' does not name a type

So it looks like base is an unknown type to gcc at this point and pre-declaring it obviously makes it cry since deriving from an incomplete type is forbidden.

I really don't see the problem here (except for the error message of course).

Can someone enlighten me?

1

There are 1 best solutions below

0
On

Ha! Searching using google for my problem didn't help me, but the related questions tab in stackoverflow did ;)

For reference, the solution is this:

In header files if you only have pointers to a class you should

  1. predeclare the class (that's what I did before), like

    class otherclass;

    in base.h and derived.h, and

    class derived;

    in otherclass.h, but

  2. do not include the corresponding header files. Only include them in their .cpp files (that's what I failed at).

Explanation: Since pointers are always of the same size and their target type is only relevant if you actually work with (i.e. dereference) them, it totally suffices for gcc to accept a derived* if you tell it about the existence of the identifier "derived" (i.e. predeclaration). In fact you are fine if you avoid any inclusion of (own) header files whose type is only used in such a way (does not need to be complete).