Classes C ++ aninhados erro declaração para a frente
-
10-07-2019 - |
Pergunta
Eu estou tentando declarar e usar um dentro classe B de uma classe A
e definir B fora A.
Eu sei para um fato que isso é possível porque Bjarne Stroustrup
usa isso em seu livro "The C ++ linguagem de programação"
(Página 293, por exemplo, as classes String e SREP).
Portanto, esta é a minha peça mínima de código que causa problemas
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() {
}
Este código dá os seguintes erros de compilação em 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’
Eu tentei olhar para o ++ Faq C ea closeset que recebi foi aqui e aqui mas
aqueles não se aplicam a minha situação.
Eu também ler este a partir daqui, mas não é resolver o meu problema.
Ambos gcc e MSVC 2005 erros do compilador dar a este
Solução
Definir o construtor para A após a definição de struct B.
Outras dicas
O c->i
expressão dereferences o ponteiro para struct A::B
assim uma definição completa deve ser visível neste momento no programa.
A correção mais simples é fazer com que o construtor de A
não-inline e fornecer um corpo para ele após o defintion de struct A::B
.
Este é um bom exemplo de por que você deseja manter as definições de separar declarações. Você precisa mudar a ordem das coisas para que o A::A()
construtor é definido após a definição de struct A::B
.
class A
{
struct B;
B* c;
A();
};
struct A::B
{
int i;
};
A::A() { c->i; }
int main()
{
return 0;
}
Curiosamente, eu cruzei para o mesmo problema com a página 293 ('11 .12 A classe String) mencionado no livro Stroustrup.
O exemplo fornecido no livro impresso parece estar em falta, fornecendo os métodos seguintes como em linha, em vez de defini-los depois a definição de estrutura 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...
Eu pesquisei um pouco, e encontrou mais recente implementação do autor desta classe String, disponível aqui: http://www2.research.att.com/~bs/string_example.c
Ele parece ter modificado a fim de que esses métodos não são mais em linha, para evitar o problema mencionado neste segmento.