views:

71

answers:

4

Hi, i'm pretty new at using C++ and I'm actually stopped at a problem.

I have some class A,B,C defined as follow (PSEUDOCODE)

class A
{
...
    DoSomething(B par1);
    DoSomething(C par1);
...
}

class B
{
   A parent;
...
}

class C
{
   A parent;
...
}

The problem is :

How to make this? If I simply do it (as I've always done in c#) it gives errors. I pretty much understand the reason of this. (A isn't already declared if I add the reference (include) of B and C into its own header)

Any way to go around this problem? (Using void* pointer is not the way to go imho)

+5  A: 

Forward-declare B and C. This way compiler will know they exist before you reach the definition of class A.

class B;
class C;

// At this point, B and C are incomplete types:
// they exist, but their layout is not known.
// You can declare them as function parameters, return type
// and declare them as pointer and reference variables, but not normal variables.
class A
{
    ....
}

// Followed by the *definition* of B and C.

P. S.

Plus, one more tip unrelated to the question (seeing how you come from a C# background): it's better to pass by const reference than by value:

class A
{
...
    void DoSomething(const B& par1);
    void DoSomething(const C& par1);
...
}
Alex B
+1  A: 

use forward declaration

You can define class A; without it's implementation, before B and C, and then define it later

paquetp
+2  A: 

You should forward declare classes B and C before A:

class B;
class C;

class A {
    ...
};

At the point where B and C are referenced within A, the compiler only needs to know what kind of animals these are. With the forward declaration you satisfy the compiler. Then later you can define them properly.

Péter Török
+1 for the semicolon after the class definition!
Luc Touraille
+3  A: 

For function declarations, parameter types are allowed to be incomplete if the function is not defined there:

class B;
class C;

class A
{
...
    R DoSomething(B par1);
    R DoSomething(C par1);
...
}

class B
{
   A parent;
...
}

class C
{
   A parent;
...
}

inline R A::DoSomething(B par1) { ... }
inline R A::DoSomething(C par1) { ... }

So you just define them after B and C become complete. But since they are defined outside the class, make them inline so multiple definitions in different translation units won't cause linker errors.

Johannes Schaub - litb
rotoglup