469,282 Members | 1,977 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

Horrible include problem

I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.
I've done this, so far with success.
However now I want to create a class A, that manages a
load of objects of type class B on the heap (using a
CTypedPtrList<CObList, ClassB*>, performing various
operations on them and then calling delete on them in its
constructor. However I want to have a variable in the
manager class that the objects can all reference,
consequently all the objects have to have a reference to
the manager class, which means they need to know its
definition. Thus, class A has to be able to 'see' class B,
and class B has to be able to 'see' class A, when
compiling. How do I arrange the include statements so that
it doesn't get either 'redefinition' or 'must have
class/struct/union type'?

Nov 16 '05 #1
6 1778
Searching google for "forward class declaration cpp" returned this:
http://www.eventhelix.com/RealtimeMa...dePatterns.htm
Hope that helps!
Elias
Nov 16 '05 #2
Ben Taylor wrote:

I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.
I've done this, so far with success.


I see you got a good answer, but as an aside... If "somebody" said to
put all the includes in stdafx.h they did you a horrible disservice.
This gives you the exact opposite of object-oriented programming, and it
considerably slows down compilation time (i.e. your time) as well.
Includes are confusing when one is a newbie - but they (usually) become
easy once you understand the compiler's simple-minded needs.

--
Scott McPhillips [VC++ MVP]
Nov 16 '05 #3
Ben Taylor wrote:

I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.


You should not put header includes that will change frequently in
stdafx.h. The whole point to it is to allow you to precompile the
headers that don't change, and that will be negated by putting
everything there.

(This is particularly important for the windows headers, which will
change only rarely. They're quite large and they take a significant
amount of time to process. By precompiling them, you realize a
substantial savings on every file you compile that incldues them.)

If you really want a more global include file, do one separately from
stdafx.h.

--
Craig Powers
MVP - Visual C++
Nov 16 '05 #4
Excellent, thanks. see response to Craig.

"Scott McPhillips" <sc******@mvps.org> wrote in message
news:3F***************@mvps.org...
Ben Taylor wrote:

I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.
I've done this, so far with success.


I see you got a good answer, but as an aside... If "somebody" said to
put all the includes in stdafx.h they did you a horrible disservice.
This gives you the exact opposite of object-oriented programming, and it
considerably slows down compilation time (i.e. your time) as well.
Includes are confusing when one is a newbie - but they (usually) become
easy once you understand the compiler's simple-minded needs.

--
Scott McPhillips [VC++ MVP]

Nov 16 '05 #5
Yes, cheers Carl. That's essentially exactly what I did in a little test at
work today after seeing lallous's website, although here in your example
you've included ClassA.h and ClassB.h twice - once in each of ClassA.cpp and
ClassB.cpp - would that not cause it to throw a refefinition wobbly? Or do
you need inclusion guards, do these work for classes as well as #defines?
Also please see my response to Craig that I'm not exactly sure how msdev
decides what order the .cpp files should get compiled in.
"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:%2*****************@tk2msftngp13.phx.gbl...
Ben Taylor wrote:
I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.
I've done this, so far with success.
However now I want to create a class A, that manages a
load of objects of type class B on the heap (using a
CTypedPtrList<CObList, ClassB*>, performing various
operations on them and then calling delete on them in its
constructor. However I want to have a variable in the
manager class that the objects can all reference,
consequently all the objects have to have a reference to
the manager class, which means they need to know its
definition. Thus, class A has to be able to 'see' class B,
and class B has to be able to 'see' class A, when
compiling. How do I arrange the include statements so that
it doesn't get either 'redefinition' or 'must have
class/struct/union type'?
Here's one common approach - where both classes have pointers to each

other:
//-----------------------
// ClassA.h

class B; // incomplete class

class A
{
CTypedPtrList<CObjList, B*> m_list;
};
// ClassB.h

class A; // incomplete class

class B
{
A* m_a;
};

// ClassA.cpp

#include "ClassA.h"
#include "ClassB.h"

// ... ClassA member functions

// ClassB.cpp

#include "ClassB.h"
#include "ClassA.h"

// ... ClassB member functions

//-----------------------

In general, if you have a set of classes that form a circular series of
dependencies, then at least one of those dependencies has to be by pointer
or reference. In C++ it's specifically legal to declare pointers to
incomplete (or "forward defined") classes in order to implement circular
dependencies such as you described.

-cd

Nov 16 '05 #6
It would be normal for both ClassA.cpp and ClassB.cpp to include both header
files: If ClassB is to call member functions on ClassA, then it has to see
the definition of ClassA. Similarly, if ClassA needs to call member
functions of ClassB (including the constructor), then it needs to see the
definition of ClassB.

This doesn't cause any multiple definition problems as long as you haven't
put inappropriate things (like non-inline function definitions) in the
header files.

The include files should have include guards, although nothing in my example
requires them: no .cpp file includes any .h file more than once.

As for the order of compilation, it's completely undefined, except that
"stdafx.cpp" (or whatever your PCH builder is named) is compiled first.
Since each file is compiled individually, the order of compilation has no
effect on the meaning or correctness of the program.

-cd

Ben Taylor wrote:
Yes, cheers Carl. That's essentially exactly what I did in a little
test at work today after seeing lallous's website, although here in
your example you've included ClassA.h and ClassB.h twice - once in
each of ClassA.cpp and ClassB.cpp - would that not cause it to throw
a refefinition wobbly? Or do you need inclusion guards, do these work
for classes as well as #defines? Also please see my response to Craig
that I'm not exactly sure how msdev decides what order the .cpp files
should get compiled in.
"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:%2*****************@tk2msftngp13.phx.gbl...
Ben Taylor wrote:
I've asked about includes before in this group in order to
stop files being #included either twice or not at all, and
somebody said to use extern keyword for global variables
that need to be used in another cpp file, and to also put
all the includes of header files in the stdafx.h file, and
then to have every cpp file just include stdafx and
nothing else.
I've done this, so far with success.
However now I want to create a class A, that manages a
load of objects of type class B on the heap (using a
CTypedPtrList<CObList, ClassB*>, performing various
operations on them and then calling delete on them in its
constructor. However I want to have a variable in the
manager class that the objects can all reference,
consequently all the objects have to have a reference to
the manager class, which means they need to know its
definition. Thus, class A has to be able to 'see' class B,
and class B has to be able to 'see' class A, when
compiling. How do I arrange the include statements so that
it doesn't get either 'redefinition' or 'must have
class/struct/union type'?


Here's one common approach - where both classes have pointers to
each other:

//-----------------------
// ClassA.h

class B; // incomplete class

class A
{
CTypedPtrList<CObjList, B*> m_list;
};
// ClassB.h

class A; // incomplete class

class B
{
A* m_a;
};

// ClassA.cpp

#include "ClassA.h"
#include "ClassB.h"

// ... ClassA member functions

// ClassB.cpp

#include "ClassB.h"
#include "ClassA.h"

// ... ClassB member functions

//-----------------------

In general, if you have a set of classes that form a circular series
of dependencies, then at least one of those dependencies has to be
by pointer or reference. In C++ it's specifically legal to declare
pointers to incomplete (or "forward defined") classes in order to
implement circular dependencies such as you described.

-cd

Nov 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Matthew | last post: by
2 posts views Thread by Stephen Thorne | last post: by
140 posts views Thread by Oliver Brausch | last post: by
2 posts views Thread by andrew lowe | last post: by
reply views Thread by Hakuin | last post: by
5 posts views Thread by Tio | last post: by
1 post views Thread by CARIGAR | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.