Re: circular dependencies, unrecognized base types, oh-my

From: John Harrison (john_andronicus_at_hotmail.com)
Date: 06/26/04


Date: Sat, 26 Jun 2004 09:20:01 +0100


"crichmon" <crichmon23@hotmail.com> wrote in message
news:J_9Dc.14238$bs4.12937@newsread3.news.atl.earthlink.net...
> Any general advice for dealing with circular dependencies? For example, I
> have a situation which, when simplified, is similar to:
>
> /////////////
> // A.h
>
> class A
> {
> public:
> int x;
> };
>
> /////////////
> // B.h
>
> #include "A.h"
> #include "C.h"
>
> class B: public A
> {
> public:
> C* myC;
> };
>
> ////////////
> // C.h
>
> #include "B.h"
>
> class C
> {
> public:
> B* myB;
> };
>
> ////////////
>
> The problem that I am having is that if I don't add some kind of forward
> declaration in B.h and/or C.h, B and/or C will be undefined when
processing
> C.h or B.h (respectively). My first question here is in a case like this,
> should I put a forward declaration of C in B.h and of B in C.h?

Yes.

> Only one is
> necessary, but it all depends on which header file the compiler reaches
> first.

You can't sensibly control which header file the compiler reaches first. Use
forward decalrations in both cases.

>
> And now for the compounded problem... I've altered C.h to include a
forward
> declaration of B after B.h is included,

What is the point of having a forward declaration *after* B.h has been
included.

> and the first problem (above) goes
> away. I have some other code (not simplified and included) in C.h that
> explicitly accesses the x integer of B's base class (in C.h: myB->A::x).
> The compiler is giving me an error, saying that " 'A' is not a base type
for
> type 'B' ". Arg! What's going on here?

C.h include B.h, C.h includes A.h, A.h includes C.h. This is a mess isn't
it?

When classes are this interdependent, it's really not a good idea to put
them in seperate header files.

Here's what I suggest, in one header file. I've added void C::func() to
represent the code in C that accesses A::x

class B;
class C;

class A
{
public:
    int x;
};

class C
{
public:
    void func();
    B* myB;
};

class B: public A
{
public:
    C* myC;
};

// now A, B and C are fully defined so we can place any code that uses them
here

inline void C::func()
{
    myB->x;
}

Simple.

john



Relevant Pages

  • Re: Share .cpp and .h along projects
    ... You asked me to show how a volatile pointer could be used to ... volatile void* or a cast could be used). ... As you stated "A compiler that can see into all these functions will ...
    (microsoft.public.vc.language)
  • Re: Confusion in ANSI Cs function concepts
    ... is no function declaration corresponding to the function call and the ... should assume a declaration with an int return type. ... the compiler will assume that fun is a function returning int ... in the above case the return type is mentioned as void *. ...
    (comp.lang.c)
  • Re: #include
    ... connects to the this header file and the respective function is ... this is often used to separate declaration from implementation. ... compile the .c file using the -c switch, or you can build a library. ... mex-file) and use #include to give the compiler the function's ...
    (comp.soft-sys.matlab)
  • Re: #include question
    ... >>The definition of a class or template tells the compiler what to do when ... After the compiler has created all the objects of a ... > By default a variable is defined (which includes declaration) unless it ... > A function is usually declared in a header file. ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Meaning of iniline in declspec(dllexport)
    ... __declspecvoid g; ... If you change the imports to exports and compile a DLL, ... pretend g and X came from a DLL header file that was ... the compiler when it is compiling the different module containing h. ...
    (microsoft.public.vc.mfc)