C ++ Вложенные классы ошибка прямого объявления - PullRequest
7 голосов
/ 22 ноября 2008

Я пытаюсь объявить и использовать класс B внутри класса A и определите B вне A.
Я точно знаю, что это возможно, потому что Бьярне Страуструп
использует это в своей книге "Язык программирования 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 голосов
/ 22 ноября 2008

Выражение c->i разыменовывает указатель на struct A::B, поэтому полное определение должно быть видно в этой точке программы.

Самое простое исправление - сделать конструктор A не встроенным и предоставить тело для него после определения struct A::B.

11 голосов
/ 22 ноября 2008

Определить конструктор для A ПОСЛЕ определения структуры B.

7 голосов
/ 22 ноября 2008

Это хороший пример того, почему вы хотите отделить определения от объявлений. Вам нужно изменить порядок вещей, чтобы конструктор A::A() был определен после определения struct A::B.

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

struct A::B
{
    int i;
};

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

int main()
{
    return 0;
}
1 голос
/ 19 октября 2010

Интересно, что я столкнулся с той же проблемой со страницей 293 ('11 .12 A String Class '), упомянутой в книге Страуструпа.

Пример, приведенный в печатной книге, по-видимому, ошибочен, предоставляя следующие методы как inline, вместо определения их после определения 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...

Я немного погуглил и нашел последнюю авторскую реализацию этого класса String, доступную здесь: http://www2.research.att.com/~bs/string_example.c

Кажется, он изменил его, чтобы эти методы больше не были встроенными, чтобы избежать проблемы, упомянутой в этой теме.

...