LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C++ interdependant classes (https://www.linuxquestions.org/questions/programming-9/c-interdependant-classes-883227/)

MTK358 05-28-2011 02:47 PM

C++ interdependant classes
 
I have two C++ classes that depend on each other. Here's a simple example:

Code:

class A
{
public:
        B foo() {}
};

class B
{
public:
        A bar() {}
};

int main()
{
        return 0;
}

It fails to compile:

Code:

$ g++ test.cpp
test.cpp:4:2: error: ‘B’ does not name a type

Is it possible to make this work?

paulsm4 05-28-2011 02:49 PM

Sure:
Code:

class B;

class A
{
public:
        B foo() {}
};

class B
{
public:
        A bar() {}
};

int main()
{
        return 0;
}


johnsfine 05-28-2011 03:43 PM

I guess there could be cases simple enough that works (just predeclaring B).

Quote:

Originally Posted by paulsm4 (Post 4369607)
Code:

class B;

class A
{
public:
    B foo() {}
};

class B
{
public:
    A bar() {}
};

int main()
{
    return 0;
}


But in most real world examples, you need to go a step further:

Code:

class B;

class A
{
public:
    B foo();
};

class B
{
public:
    A bar() {}
};

B A::foo() {}

int main()
{
    return 0;
}

In addition to predeclaring B before defining A, I also only declared (not defined) foo inside the definition of A. Then I defined A::foo after defining B.

(In all these examples, I am assuming the {} stands for actual code rather than literally {})

You (MTK358) need to understand the relationship between declaring and defining:

The code in the first post declares and defines A together as one step, similarly for foo, B and bar. But each of those could have declare split from define if you choose.

You cannot avoid declaring A::foo() within defining A, and you cannot avoid declaring B::bar() within defining B.

The way the code looks, it is very clear:
1) Declaring B must precede declaring foo.
2) Declaring A must precede declaring bar.
It seems pretty clear (despite paulsm4's example):
3) Defining B must precede defining foo.
4) Defining A must precede defining bar.

My example sorts all that out by the following sequence:
Declaring B
Defining A including declaring foo
Defining B including declaring and defining bar
Defining foo.

It may be better style (though not needed in this example) to also split defining bar from declaring bar.

paulsm4 05-28-2011 10:40 PM

Hi, Mtk358 -

Glad you're squared away. Let me elaborate a bit on what johnsfine was trying to say:

1. You should always strive to separate your interface from your implementation (one of the few things I dislike about Java and C# is they tend to make it harder to do this).

2. If you did this, your interface would go in a .h header, your implementation in one or more .cpp modules ... and the syntax I gave you should work perfectly.

3. Otherwise, you might have problems trying to access any members of the class you forward referenced.

Here's an alternate example:
Code:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

class B;

class A
{
public:
  A ();
  void someMethod ();
  void someOtherMethod ();
...
  B foo;
};

class B
{
public:
  B ();
  ...
  A bar;
};
#endif
/* MYHEADER_H */

Code:

// mymodule.cpp
#include "myheader.h"

A::A ()
  : foo()
{
  ...
    B foo() {}
};

B::B ()
  : bar()
{
public:
    A bar() {}
};

int main()
{
  ...
}


MTK358 05-29-2011 08:29 AM

I do separate the interface and implementation. I didn't in the example becasue it's simpler and still causes the same error.

Sergei Steshenko 05-29-2011 01:06 PM

http://stackoverflow.com/questions/3...ursive-classes - pay attention to pointers to classes.

paulsm4 05-29-2011 01:28 PM

MTK358 -
Quote:

I do separate the interface and implementation.
Sorry - I didn't mean to imply that you wouldn't ordinarily do that. I just wanted to make sure you were crystal-clear with all the responses to your original question (including mine).

Again - glad you're squared away :)

Sincerely .. PSM


All times are GMT -5. The time now is 02:44 AM.