C ++ Вложенные классы ошибка прямого объявления
-
10-07-2019 - |
Вопрос
Я пытаюсь объявить и использовать класс 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а> р>
Похоже, он изменил его, чтобы эти методы больше не были встроенными, чтобы избежать проблемы, упомянутой в этой теме.