tags:

views:

89

answers:

7

hi, i hope there's a simple answer to this. without getting too complicated i have two classes. an "Animal" and a "Cell" Cell contains an Animal as a member. Animal has methods that accept Cells in their parameters.

i'm just confused as to how i #include each class the others header? i've only ever had to go up a chain of classes and just included the last class header in the next and so on, but this circular situation has me a bit lost.

i hope that makes sense, any help greatly appreciated.

+1  A: 

Cyclic dependencies are handled with forward declarations (scroll to the bottom of the page).

Rytmis
+1  A: 

You need to forward declare one of the classes so that the compiler knows about it. Kind of like, there's this class "Animal", i'll tell you what it is later.

Example:

class Animal;

class Cell
{
    Animal *a;
};

class Animal
{
    Cell *c;
};

As Gareth notes in the comments, you may not forward declare something that will be passed by value. This is because the compiler can only deal with types that it knows the size of. A pointer to anything is always the same size, so the compiler does require Animal to be fully defined in the above example.

This will not work:

class Animal;

class Cell
{
    Animal a; // compiler needs to know how Animal is defined
}             // and so will fail at this point
Jacob Stanley
-1: forward declaration does not allow you to define a member by value, only by pointer or reference. So, in your example above - after forward-declaring `class Animal`, `Cell` could have an `Animal* a` member, but not `Animal a`.
Gareth Stockwell
Ahh sorry, I will correct it
Jacob Stanley
Downvote removed.
Gareth Stockwell
My C++ is a bit rusty :)
Jacob Stanley
spot on, thank you.
Julz
you're exactly right gareth, it is a pointer.thanks
Julz
+1  A: 

If Cell contains Animal as a member then a full definition of Animal is needed before Cell is defined so you would need to #include the header that defines Animal from the header that defines Cell.

#include "animal.h"

class Cell
{
    // ...
    Animal animal; // animal member
};

If Animal has methods that take or return a Cell (whether by reference or value) then you can just forward declare Cell before the definition of Animal like this.

// animal.h
class Cell;

class Animal
{
    // declarations of Animal methods
};
Charles Bailey
+3  A: 

You can use forward declarations to overcome the problem of circular references.

Example:

//animal.h

#include "cell.h"

class Animal {
public:
    void foo (Cell cell);
}

// cell.h

class Animal; // forward declaration

class Cell {
private:
    Animal * m_animal; // pointer to Animal object
}
swegi
brilliant!thanks heaps, i figured there was a simple solution.thanks again
Julz
@Julz: It's better to pass by reference, and question specified a different relationship for Animal within Cell…
Potatoswatter
yep, my bad. i'll be more specific next time.
Julz
A: 

It's not possible for two classes each to contain objects of the other's type - one or both of the classes will have to contain a pointer to the other's type.

anon
+1  A: 

animal.h:

class Cell; // fwd declaration

// Cell is now an "incomplete type"

class Animal {
    void Respirate( Cell & ); // reference: no need for complete type
};

cell.h:

#include "animal.h"

class Cell {
    Animal organism; // conceptually, a reference or pointer would be better
};

OR

class Animal

class Cell {
    Animal *organism; // Cell "knows about an" animal rather than "has an"
};
Potatoswatter
A: 

You can forward declare, but this doesn't completely solve the problem, it only lets you declare a pointer to that object, not use any functions/members inside that object. You can do this:

Animal.h

class Cell;

class Animal {
  private:
  Cell cell;
};

Animal.cpp

#include "Animal.h"
#include "Cell.h"

// Animal functions can use members/functions in Cell object here

Cell.h

class Animal;

class Cell
{
  private:
    Animal animal;
};

Cell.cpp

#include "Animal.h"
#include "Cell.h"

// Cell functions can use members/functions in Animal object here

This way both objects are able to completely use the features of the other (except in the headers, but that's fine)

James
OK but your members need to be pointers like others have mentioned..
James