Cuando el compilador compila la clase User
y llega a la línea MyMessageBox
, MyMessageBox
aún no se ha definido. El compilador no tiene idea MyMessageBox
existe, por lo que no puede entender el significado de su miembro de la clase.
Debe asegurarse de MyMessageBox
se define antes de lo utiliza como miembro. Esto se resuelve invirtiendo el orden de definición. Sin embargo, tiene una dependencia cíclica: si mueve MyMessageBox
sobre User
, entonces en la definición de MyMessageBox
no se definirá el nombre User
.
Lo que puedes hacer es delantero declararUser
; es decir, declararlo pero no definirlo. Durante la compilación, un tipo declarado pero no definido se llama tipo incompleto. Considere el ejemplo más sencillo:
struct foo; // foo is *declared* to be a struct, but that struct is not yet defined
struct bar
{
// this is okay, it's just a pointer;
// we can point to something without knowing how that something is defined
foo* fp;
// likewise, we can form a reference to it
void some_func(foo& fr);
// but this would be an error, as before, because it requires a definition
/* foo fooMember; */
};
struct foo // okay, now define foo!
{
int fooInt;
double fooDouble;
};
void bar::some_func(foo& fr)
{
// now that foo is defined, we can read that reference:
fr.fooInt = 111605;
fr.foDouble = 123.456;
}
Por delante declarar User
, MyMessageBox
todavía se puede formar un puntero o referencia a ella:
class User; // let the compiler know such a class will be defined
class MyMessageBox
{
public:
// this is ok, no definitions needed yet for User (or Message)
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message>* dataMessageList;
};
class User
{
public:
// also ok, since it's now defined
MyMessageBox dataMsgBox;
};
Usted no puede hacerlo al revés: como se ha mencionado, un miembro de la clase necesita tener una definición. (La razón es que el compilador necesita saber la cantidad de memoria User
ocupa, y saber que lo que necesita saber el tamaño de sus miembros.) Si se va a decir:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
No funcionaría , ya que aún no conoce el tamaño.
En una nota lateral, esta función:
void sendMessage(Message *msg, User *recvr);
probablemente no debería adoptar una de las de puntero. No puede enviar un mensaje sin un mensaje, ni puede enviar un mensaje sin un usuario para enviarlo. Y esas dos situaciones son expresables mediante el paso nulo como un argumento para cualquiera de los parámetros
Más bien, utilizar una referencia (posiblemente const) (nulo es un valor de puntero perfectamente válido!):
void sendMessage(const Message& msg, User& recvr);
Los tiempos infinitos me sale este error, solo para darme cuenta de que las guardias de importación generadas por el IDE están duplicadas – Mazyod
Tenga en cuenta que también puede obtener este error si coloca una referencia externa a una declaración en un archivo .h/.hpp antes de que se defina la clase, incluso cuando tenga la declaración real después de la inclusión .h/.hpp dentro del archivo .cpp. – Owl
@Mazyod. Gracias Gracias. No pude entender qué demonios estaba causando este extraño error. –