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 nogccRespuestas:
Cuando el compilador compila la clase
Usery llega a laMyMessageBoxlínea,MyMessageBoxaún no se ha definido. El compilador no tiene idea de queMyMessageBoxexiste, por lo que no puede entender el significado de su miembro de clase.Debe asegurarse de que
MyMessageBoxesté 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 haciaMyMessageBoxarribaUser, ¡en la definición delMyMessageBoxnombreUserno 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,MyMessageBoxaú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
Userocupa 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
MyMessageBoxhabría sido suficiente. ¿Y si tambiénMyMessageBoxtuviera una variable de tipoUser? ¿Sería un punto muerto?Userque tendría unMessageBoxque tendría unUser, que tendría unMessageBoxque tendría unUser, que tendría unMessageBoxque tendría unUser, que tendría unMessageBoxque tendría unUser...fuente
Los compiladores de C ++ procesan su entrada una vez. Cada clase que use debe haber sido definida primero. Lo usa
MyMessageBoxantes de definirlo. En este caso, simplemente puede intercambiar las dos definiciones de clase.fuente
MyMessageBoxhaUserescrito 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.Usertipo 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
Userclase en un archivo de encabezado (User.h) y laMyMessageBoxclase en otro archivo de encabezado (MyMessageBox.h). Luego en tuUser.hincluyesMyMessageBox.hy enMyMessageBox.htu incluyesUser.h. No olvide "incluir gaurds" [ 2 ] para que su código se compile correctamente.fuente