File Dog.h
#ifndef DOG_H
#define DOG_H
#include "Cat.h"
//class Cat;
class Dog
{
Cat c;
};
#endif
File Cat.h
#ifndef CAT_H
#define CAT_H
#include "Dog.h"
//class Dog;
class Cat
{
Dog d;
};
#endif
This causes a loop, the problem is that both classes needs to know about each other; forward declaration doesn't solve the problem either. You can create a pointer of either Dog d or Cat c to solve it.
Question: Is there really no way of not creating a pointer, i.e keep the code as it is without rewrite of how I want it to be?
Besides this leading to an infinite space object (as Raphael explains), the compiler won't let this happen as explained in this question. He doesn't know about
Cat
class when you are using it inDog
class, so it won't work for the same reason that this won't work :No, this is not possible, and it has nothing to do with include files.
The reason is that if you create a class which contains another class as a member (rather than a pointer), the compiler needs to add some space for that class into the other class. E.g., if you create something like this:
Then instances of the class
Person
in the above example have a size that issizeof(std::string) + sizeof(Dog)
, while instances of the classDog
have a size that issizeof(std::string) * 2
; so Person issizeof(std::string) * 3
in size (modulo alignment differences)In other words, the memory required for a first-class variable (as opposed to a pointer) in C++ is assigned as part of the instance, and is not a pointer; this works very much the same way as
struct
s do. In fact, there really is no practical difference between theclass
andstruct
keywords in C++, other than the fact that a class isprivate
by default, whereas a struct ispublic
.What you're trying to do is impossible. Your class would take infinite space.
You got a
Dog
which has aCat
member variable, which has aDog
member variable, which has aCat
member variable, which has aDog
member variable...Without breaking it somewhere with a pointer you'll end up with infinite recursive member variables taking infinite memory which is not possible.
Note that the compiler can't even actually calculate the memory needed for
Dog
orCat
due to the infinite recursion. But since a class in C++ can't be0
size normally, we know that it'll be infinite space anyways.The other answers give nice perspectives too, i.e. 'Chicken and Egg' problem of which one has to be defined first to be able to define the other.
I just wanna add that mutually recursive classes are something strange and best avoided if you can design it some other way. If you really have to use them make sure that you actually break the recursiveness. Otherwise you shift it only from an error at compile time due to infinite mutual recursion to running out of memory and an crash at runtime if you got a naive implementation with pointers that does infinite mutually recursive
new
calls at construction time.As already pointed out, you cannot directly or indirectly define an object that has itself as a member without indirection.
If you only want the ability to use the
.
syntax instead of the->
syntax, you can use a reference instead of a pointer. For example:Now, in your source code, you can do something like this: