Classes that reference classes

Pages: 12
Oct 30, 2014 at 9:28pm
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?
Oct 30, 2014 at 9:54pm
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.
Oct 30, 2014 at 10:03pm
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 Oct 30, 2014 at 10:04pm
Oct 30, 2014 at 10:05pm
Oct 30, 2014 at 10:20pm
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.
Oct 30, 2014 at 11:11pm
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 Oct 30, 2014 at 11:13pm
Oct 30, 2014 at 11:12pm
declarations are contained in header files, definitions in code files. this lets you include the declarations of each class within the other classes.
Oct 31, 2014 at 8:24am
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 Oct 31, 2014 at 8:30am
Oct 31, 2014 at 8:56am
It's not a forward definition, it's a forward declaration.
Oct 31, 2014 at 9:01am
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 Oct 31, 2014 at 9:01am
Oct 31, 2014 at 9:18am
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.
Oct 31, 2014 at 9:25am
@Essl, You could just inline it or use safeguards.
Oct 31, 2014 at 9:37am
Codeblocks automatically puts include guards on my header files so that isn't a problem.
Oct 31, 2014 at 9:39am
...... 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.

:+)
Oct 31, 2014 at 9:51am
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.
Oct 31, 2014 at 9:59am
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 Oct 31, 2014 at 10:00am
Oct 31, 2014 at 10:04am
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.

:+)
Oct 31, 2014 at 10:07am
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 Oct 31, 2014 at 10:08am
Oct 31, 2014 at 10:12am
@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 Oct 31, 2014 at 10:17am
Oct 31, 2014 at 10:26am
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