Вопрос

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

И gcc, и MSVC 2005 выдают ошибки компилятора на этом

Это было полезно?

Решение

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

Другие советы

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

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

Это хороший пример того, почему вы хотите отделить определения от объявлений. Вам нужно изменить порядок вещей, чтобы конструктор 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;
}

Интересно, что я столкнулся с той же проблемой со страницей 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...

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

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

scroll top