Tengo dos clases declaradas de la siguiente manera:
class User
{
public:
MyMessageBox dataMsgBox;
};
class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};
Cuando intento compilarlo usando gcc, aparece el siguiente error:
MyMessageBox no nombra un tipo
g++
y nogcc
Respuestas:
Cuando el compilador compila la clase
User
y llega a laMyMessageBox
línea,MyMessageBox
aún no se ha definido. El compilador no tiene idea de queMyMessageBox
existe, por lo que no puede entender el significado de su miembro de clase.Debe asegurarse de que
MyMessageBox
esté definido antes de usarlo como miembro. Esto se resuelve invirtiendo el orden de definición. Sin embargo, tiene una dependencia cíclica: si se mueve haciaMyMessageBox
arribaUser
, ¡en la definición delMyMessageBox
nombreUser
no se definirá!Lo que puede hacer es declarar hacia adelante
User
; es decir, declararlo pero no definirlo. Durante la compilación, un tipo que se declara pero no se define se denomina tipo incompleto . Considere el ejemplo más simple:Al declarar hacia adelante
User
,MyMessageBox
aún puede formar un puntero o hacer referencia a él:No puede hacer esto al revés: como se mencionó, un miembro de la clase necesita tener una definición. (La razón es que el compilador necesita saber cuánta memoria
User
ocupa y saber que necesita saber el tamaño de sus miembros). Si tuviera que decir:No funcionaría, ya que aún no conoce el tamaño.
En una nota al margen, esta función:
Probablemente no debería tomar ninguno de esos por puntero. No puede enviar un mensaje sin un mensaje, ni puede enviar un mensaje sin un usuario a quien enviarlo. Y ambas situaciones se pueden expresar pasando nulo como argumento a cualquier parámetro (¡nulo es un valor de puntero perfectamente válido!)
Más bien, use una referencia (posiblemente constante):
fuente
MyMessageBox
habría sido suficiente. ¿Y si tambiénMyMessageBox
tuviera una variable de tipoUser
? ¿Sería un punto muerto?User
que tendría unMessageBox
que tendría unUser
, que tendría unMessageBox
que tendría unUser
, que tendría unMessageBox
que tendría unUser
, que tendría unMessageBox
que tendría unUser
...fuente
Los compiladores de C ++ procesan su entrada una vez. Cada clase que use debe haber sido definida primero. Lo usa
MyMessageBox
antes de definirlo. En este caso, simplemente puede intercambiar las dos definiciones de clase.fuente
MyMessageBox
haUser
escrito en su declaración de método.User
. Distinción importante, porque eso significa que la clase User solo debe declararse en ese punto, no definirse . Pero vea la extensa publicación de GMan.User
tipo aún no está declarado.Debe definir MyMessageBox antes que User, porque el usuario incluye el objeto de MyMessageBox por valor (por lo que el compilador debe conocer su tamaño).
También deberá reenviar declare User antes de MyMessageBox, porque MyMessageBox incluye un miembro del tipo User *.
fuente
En una nota relacionada, si tuvieras:
Entonces eso también funcionaría, porque el usuario está definido en MyMessageBox como un puntero
fuente
Debes declarar el prototipo antes de usarlo:
editar : intercambiado los tipos
fuente
Siempre se recomienda en C ++ que tenga una clase por archivo de encabezado, vea esta discusión en SO [ 1 ]. La respuesta de GManNickG dice por qué sucede esto. Pero la mejor manera de resolver esto es poner la
User
clase en un archivo de encabezado (User.h
) y laMyMessageBox
clase en otro archivo de encabezado (MyMessageBox.h
). Luego en tuUser.h
incluyesMyMessageBox.h
y enMyMessageBox.h
tu incluyesUser.h
. No olvide "incluir gaurds" [ 2 ] para que su código se compile correctamente.fuente