Я пытаюсь объявить и использовать класс B внутри класса A
и определим B вне A.
Я точно знаю, что это возможно, потому что 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 выдают ошибки компилятора в этом
Выражение c->i
разыменовывает указатель на struct A::B
, поэтому полное определение должно быть видно на этом этапе программы.
Самое простое исправление - сделать конструктор A
не встроенным и предоставить ему тело после определения struct A::B
.
Определите конструктор для A ПОСЛЕ определения структуры B.
Конструктор определяется после объявления B. Его необходимо определить после определения 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
Кажется, он изменил его так, чтобы эти методы больше не были встроенными, чтобы избежать проблемы, упомянутой в этом потоке.
Или определите функцию как встроенную, используя ключевое слово
inline
после определения структуры B.