C++ 嵌套类前向声明错误

7
我想在类A中声明和使用类B,并在类A外定义类B。 我确信这是可能的,因为Bjarne Stroustrup在他的书“C ++编程语言”(例如第293页的String和Srep类)中使用了这种方法。
以下是导致问题的最小代码片段:
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() {
}

这段代码在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’

我尝试查看了C++ Faq,最接近的是这里这里,但它们不适用于我的情况。我也从这里阅读了内容,但它并没有解决我的问题。
gcc和MSVC 2005都对此给出了编译器错误。
4个回答

15

表达式c->i将指向struct A::B的指针解引用,因此在程序的此处必须可见完整的定义。

最简单的解决方法是使A的构造函数非内联并在struct A::B的定义后提供其主体。


或者,在结构体B的定义之后使用inline关键字将函数定义为内联函数。 - Phlucious

11
在结构体B的定义之后为A定义构造函数。

1
构造函数在B被声明之后定义。它需要在B被定义之后定义。 - Steve Jessop
更新以将“声明”替换为“定义”。 :-) - Paul Sonier

7
这是为什么要将定义与声明分开的一个很好的例子。您需要改变事物的顺序,以便在定义struct A::B之后再定义构造函数A::A()
class A
{
    struct B;
    B* c;
    A();
};

struct A::B
{
    int i;
};

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

int main()
{
    return 0;
}

1
有趣的是,我在Stroustrup的书中也遇到了293页(“11.12 A String Class”)中提到的同样问题。
印刷版书中提供的示例似乎有误,将以下方法作为内联方法提供,而不是在定义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...

我在谷歌上搜索了一下,找到了作者最新的字符串类实现,可以在这里找到: http://www2.research.att.com/~bs/string_example.c

他似乎已经修改了它,使得这些方法不再是内联的,以避免在这个线程中提到的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接