views:

5624

answers:

4

I am trying to declare and use a class B inside of a class A and define B outside A.
I know for a fact that this is possible because Bjarne Stroustrup
uses this in his book "The C++ programming language"
(page 293,for example the String and Srep classes).

So this is my minimal piece of code that causes problems

class A{
struct B; // forward declaration
B* c;
A() { c->i; }
};

struct A::B { 
/* 
 * we define struct B like this becuase it
 * was first declared in the namespace A
 */
int i;
};

int main() {
}

This code gives the following compilation errors in g++ :

tst.cpp: In constructor ‘A::A()’:
tst.cpp:5: error: invalid use of undefined type ‘struct A::B’
tst.cpp:3: error: forward declaration of ‘struct A::B’

I tried to look at the C++ Faq and the closeset I got was here and here but
those don't apply to my situation.
I also read this from here but it's not solving my problem.

Both gcc and MSVC 2005 give compiler errors on this

+12  A: 

The expression c->i dereferences the pointer to struct A::B so a full definition must be visible at this point in the program.

The simplest fix is to make the constructor of A non-inline and provide a body for it after the defintion of struct A::B.

Charles Bailey
+8  A: 

Define the constructor for A AFTER the definition of struct B.

McWafflestix
yes , that worked thank you :)
xxxxxxx
You're welcome! :-)
McWafflestix
The constructor is defined after B is declared. It needs to be defined after B is defined.
Steve Jessop
yes. i suppose that's why he is being downvoted by some :)
Johannes Schaub - litb
Updated to replace "declaration" with "definition". :-)
McWafflestix
+5  A: 

This is a good example of why you want to keep definitions separate from declarations. You need to change the order of things so that the constructor A::A() is defined after the definition of struct A::B.

class A
{
    struct B;
    B* c;
    A();
};

struct A::B
{
    int i;
};

A::A() { c->i; }

int main()
{
    return 0;
}
e.James
A: 

Interestingly, I've bumped into the same problem with the page 293 ('11.12 A String Class') mentioned in the Stroustrup book.

The example provided in the printed book seems to be at fault, providing the following methods as inline, instead of defining them after the definition of struct Srep

class String {
  // ...
  void check(int i) const { if (i<0 || rep->sz <=i) throw Range(); }
  char read(int i) const { return rep->s[i]; }
  void write(int i, char c) { rep=rep->get_own_copy(); rep->s[i]=c; }
  ...etc...

I googled a bit, and found the author's latest implementation of this String Class, available here: http://www2.research.att.com/~bs/string_example.c

He seems to have modified it so that these methods are no longer inline, to avoid the problem mentioned in this thread.

Conan the Fishmonger