Public Group

#### Archived

This topic is now archived and is closed to further replies.

# Recursive Classes

This topic is 5392 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Is it possible to do something like this? Class1.h
#ifndef CLASS1_H
#define CLASS1_H
#include "class2.h"

class Class1
{
public:
Class1(){};
~Class1(){};
Class2 getClass2() {return otherClass};
void setClass2(Class2 *pClass2) {otherClass=pClass2;};

private:
Class2 *otherClass;
};
#endif

Class2.h
#ifndef CLASS2_H
#define CLASS2_H
#include "class1.h"

class Class2
{
public:
Class2(){};
~Class2(){};
Class1 getClass1() {return otherClass};
void setClass1(Class1 *pClass1) {otherClass=pClass1;};;

private:
Class1 *otherClass;
};
#endif

I know that this code will generate errors relating to a recursive reference. How do I get around this so that it will work? Thanks Extracting Patch.... Initializing Windows XP Update Path 2543663B.... Core Dumped, Now Installing Linux..... ---- Mike Team AI: Http://members.iinet.net.au/~slyons/teamai [edited by - Mike737 on August 17, 2003 2:42:08 AM]

##### Share on other sites
I assume by this line in class1.h:

#include "class1.h"

You meant:

#include "class2.h"

And no that won''t work.

In class1.h, remove the #include, and add this:

extern class Class2;

Then it should work. IIRC there was an article here on Gamedev that addressed this problem and others involved in organizing a project. Have a look for it.

##### Share on other sites
You can do it if the two classes are in the same file. If headers try to include each other you will get a precompiler error (yes even with the #ifndef/#define chode).

You can still put them in the same file though, and with as simple forward decleration of "class 2" before "class 1" it will work just fine.

Also, just as an extra side note any functions that actualy use a forwad declerated class need to defined after the classes (probably in a .cpp), and you can only keep pointers as actual member varibales. For this problem it should work fine though. Im not sure about pointer assignements though, so just to be safe I put it after the classes.

Here is a code dump (I define the functions at the bottom):

"classes.h"

#ifndef _CLASSES_H
#define _CLASSES_H

class Class2;

class Class1
{
public:
Class1(){};
~Class1(){};
Class2 *getClass2();
void setClass2(Class2 *pClass2);

private:
Class2 *otherClass;
};

class Class2
{
public:
Class2(){};
~Class2(){};
Class1 *getClass1();
void setClass1(Class1 *pClass1);
private:
Class1 *otherClass;
};

void Class1::setClass2(Class2 *pClass2)
{
otherClass = pClass2;
}

Class2 *Class1::getClass2()
{
return otherClass;
}

void Class2::setClass1(Class1 *pClass1)
{
otherClass = pClass1;
}

Class1 *Class2::getClass()
{
return otherClass;
}

#endif

hopefully that will work. This is my first time posting so any hints would be helpfull, and also how did you do that code formatting stuff;

##### Share on other sites
quote:
Original post by Mike737
How do I get around this so that it will work?

You don''t, typically. Instead you figure out another design where the two classes don''t need to reference each other like that. When this problem comes up, IMHO it''s a good indication that something is very wrong with the design.

Things get a lot cleaner organized if you think of one class as parent, and the other as child. The parent references the child, not the other way round. If the child needs to tell something to the parent, then use a separate callback object. Google for "Observer pattern".

##### Share on other sites
quote:
Original post by Anonymous Poster
quote:
Original post by Mike737
How do I get around this so that it will work?

You don''t, typically. Instead you figure out another design where the two classes don''t need to reference each other like that. When this problem comes up, IMHO it''s a good indication that something is very wrong with the design.

Things get a lot cleaner organized if you think of one class as parent, and the other as child. The parent references the child, not the other way round. If the child needs to tell something to the parent, then use a separate callback object. Google for "Observer pattern".

Sorry, but I don''t agree. It is perfectly valid design to have pointers in classes which create circular references. It''s only if you need instances of these objects that there is something wrong with the design. In the OP case, you don''t actually need any include directives. Just change the #include "class2.h" to class Class2; and the #include "class1.h" to class Class1;

There is one mistake in the code: the functions to return the classes return by value instead of a pointer. They should be:
Class2 * getClass2() { return otherClass; }
and
Class1 * getClass1() { return otherClass; }

But this was probably just a typo.

James

##### Share on other sites
Use forward declaration. This is what it''s for.

class1.h
#ifndef CLASS1H#define CLASS1Hclass class2;class class1 {     class2 * pClass2Object;//other members};

class2.h
#ifndef CLASS2H#define CLASS2Hclass class1;class class2 {     class 1 * pClass1Object;//other members};

Why is it so? Because you do not need to include a header file unless you want to know what the class looks like. In your case, you just need to know that somewhere, in another file, there is a class named "class2", and that you have a pointer to it. So you simply tell the compiler "class class2;" so it doesn''t wonder if class2 is defined.

So, when do you need to include headers? Whenever you need information about the members of a class in those headers. This includes:

-> whenever you use a member function or variable of that object (but you usually use members in the cpp file, not in the header, so no need in that case to include a header in another header).
-> whenever you need to know a constructor or destructor of that class (that is, when you create an instance of the class ).

So the following code lines needs including the Class1 header:

class X : public Class1
and
Class1 object;
and
new Class1( );
and
Class1Object->member or Class1Object.member

the following code line doesn''t :

Class1 * object;

##### Share on other sites
Thanks guys for all your help...

I used "extern class" syntax in the end, it worked the best out of all of them.

James, you guessed right... dumb assed typo

You all deserve a pizza for your efforts .

And ToohrVyk, I agree with you, but in somecases there is no way you can get around it cos of the design that have already been implemented... especially in a traditional software development lifecycle.

Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

##### Share on other sites
Aside from using templates, if you stick to this fro the beginning then there is no way in hell you ever het a circular definition problem...

• 23
• 10
• 19
• 15
• 14