Classes that reference classes

Pages: 12
I've split the main part of my program into three classes and their respective functions. I have my 'character' class that deals with the player and the main character's sprites. I have a 'stage' class that controls the background and the environment. My third class is entitled 'brain' and has a lot of other pieces of information, arrays etc and also controls the enemies.

My problem is that in my character class, I have a function that requires the input of a stage object and a brain object. But in my brain class, I have a function that requires the input of a character object and a stage object. My project won't compile because whatever order I put them in, there is always a class that has a reference to an undefined type. Is there any way I can get around this?
so long as each class is defined in it's own header/code files, you should be able to #include the header for the other classes in each of them to provide the needed declarations.
I don't think that's the problem.

Here's an example:

class A{
public:
void function(B input);
};

void A::function(B input)
{
//some code involving input of type B
}

class B{
public:
void function(A input);
};

void B::function(A input)
{
//some code involving input of type A
}

For this to work, both classes would need to be declared before any of there functions are declared or defined and I don't see how to do this.
Last edited on
I've just read that and I'm still not sure it solves the problem. Whichever way I do it, one class is defined first, even if I put include a.h before b and include b.h before a, the compiler always compiles one first. And if within that class defintion it references the other class, which cannot possibly have been defined yet, it throws up errors. However I think the following may work, which I have just thought of. Instead of giving class A a function that takes an input of B, and B a function that takes an input of A, I could do this:

Afunction(A & object, B input)
{
//code using B to affect A
}

Bfunction(B & object, A input)
{
//code using A to affect B
}

Please correct me if I am wrong.
That article addressed your exact scenario. This is the solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct B; //forward declare

struct A
{
    void f(B const &); //passing by copy would not be valid
};

struct B
{
    void f(A const &);
};

void A::f(B const &b)
{
    //...
}

void B::f(A const &a)
{
    //...
}
Pick one header to forward-declare in and pick another header to get the full include. The solution requires using cpp files.
Last edited on
declarations are contained in header files, definitions in code files. this lets you include the declarations of each class within the other classes.
Thank you. I guess the reason I didn't think it was in there was that I had never come across the term forward definition so I didn't know what it meant. For the record, is there a problem with defining in a seperate header file, or does it have to be a code file? Also, what's the difference between struct and class and does it have to be struct rather than class?
Last edited on
It's not a forward definition, it's a forward declaration.
OK, sorry I still accidentally mix the two words up when I'm not thinking about it. For the record, I do know the difference, though my previous questions still stand, can the definition be in the same header file as the declaration and what is the diffference between class and struct?
Last edited on
technically speaking, since header files are included into code files at the start of compilation, a definition can be in a header file. but you really shouldn't.

The problem is that header files are often included in more than one code file. It may compile just fine, but when the linker tries to do its job, it'll find multiple definitions of the same entity and fail.
@Essl, You could just inline it or use safeguards.
Codeblocks automatically puts include guards on my header files so that isn't a problem.
...... and what is the diffference between class and struct?


in C++, classes, structs and unions are exactly the same, except for the default access: class is private: ; while struct and union is public

1
2
3
4
5
6
7
8
MyClass {
    int m_a; // a private variable by default

};

struct MyStruct {
     int m_a; // a public variable by default
};



All the other stuff - ctor, dtor, initialiser list, functions, inheritance etc is all the same.

This is rather different in C, where a struct is more like a "record" concept, it hold has member variables only - no functions etc.

:+)
include guard do not prevent the problem. I'm saying that if the same header that contains definitions is included in two or more .cpp files, then there will be multiple definitions which will cause the linker to fail. inlining is a separate issue.
I only have one .cpp in my program and about 9 header files. I usually do it like that because I find it easier to follow. I apprciate the warning though. If I do ever add more .cpp files then I'll split up my class headers.

Also with class, struct and union, if I wanted to make a new numeric type (e.g. one with a limit of 31 that loops) would I use union?
Last edited on
Also with class, struct and union, if I wanted to make a new numeric type (e.g. one with a limit of 31 that loops) would I use union?


Not sure what you mean by that - have a read of the tutorial on this site, to see what a union does.

:+)
Don't use a union for that, just a struct or class
Unions are a rather peculiar construct in which all the members occupy the same memory. If you're not absolutely sure that you need one and why, avoid them.

http://www.cplusplus.com/doc/tutorial/other_data_types/
Last edited on
@TheIdeasMan what I meant was make a new version of unsigned char that if you go past 31, it loops. e.g. (in this case the type would be called limited unsigned char)
1
2
3
4
limited unsigned char a (0); // a = 0
a = 10; //a = 10
a = 40; //because above 31, it takes off 32 until it is less than or equal to 31 so a = 8
a = a + 30; //this would again be above 31 so it would loop and produce 6 

I would be trying to make a type that acts like in the above scenarios.

I've also just reodered my classes header so that it goes forward declarations, normal declarations, defintions and it works!
Last edited on
OK, just use a class as Esslercuffi suggested.

I only have one .cpp in my program and about 9 header files. I usually do it like that because I find it easier to follow. I apprciate the warning though. If I do ever add more .cpp files then I'll split up my class headers.


You can get CodeBlocks to automatically add function stubs into the .cpp file when you put them into the .h file.

First though, you should create the class from the menu option, not by typing directly into a file. This will create both the files automatically.

:+)
Pages: 12