У меня объявлено два класса, как показано ниже:
class User
{
public:
MyMessageBox dataMsgBox;
};
class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};
Когда я пытаюсь скомпилировать его с помощью gcc, появляется следующая ошибка:
MyMessageBox не называет тип
g++
а неgcc
Ответы:
Когда компилятор компилирует класс
User
и переходит кMyMessageBox
строке,MyMessageBox
еще не определено. Компилятор понятия не имеет, чтоMyMessageBox
существует, поэтому не может понять значение вашего члена класса.Вы должны убедиться, что
MyMessageBox
он определен, прежде чем использовать его в качестве члена. Это решается изменением порядка определения на обратный. Однако у вас циклическая зависимость: если вы переместитесьMyMessageBox
вышеUser
, то в определенииMyMessageBox
имяUser
не определится!Что вы можете сделать, так это объявить вперед
User
; то есть объявлять, но не определять. Во время компиляции тип, который объявлен, но не определен, называется неполным типом . Рассмотрим более простой пример:По вперед объявляя
User
,MyMessageBox
все еще может сформировать указатель или ссылку на него:Вы не можете сделать это наоборот: как уже упоминалось, член класса должен иметь определение. (Причина в том, что компилятор должен знать, сколько памяти
User
занимает, и знать, что ему нужно знать размер своих членов.) Если бы вы сказали:Это не сработает, так как он еще не знает размера.
Кстати, эта функция:
Наверное, не стоит брать ни одного из них по указателю. Вы не можете отправить сообщение без сообщения, а также вы не можете отправить сообщение без пользователя, которому его отправили. И обе эти ситуации можно выразить, передав null в качестве аргумента для любого параметра (null - это совершенно допустимое значение указателя!)
Скорее используйте ссылку (возможно, const):
источник
MyMessageBox
хватило бы форвардного декларирования . Что, еслиMyMessageBox
бы у переменнойUser
тоже был тип - это был бы тупик?User
будет иметь ,MessageBox
которые имели быUser
, что бы иметь ,MessageBox
которые имели быUser
, что бы иметь ,MessageBox
которые имели быUser
, что бы иметь ,MessageBox
который быUser
...источник
Компиляторы C ++ обрабатывают свой ввод один раз. Каждый используемый вами класс должен быть определен первым. Вы используете,
MyMessageBox
прежде чем определять его. В этом случае вы можете просто поменять местами определения двух классов.источник
MyMessageBox
имеетUser
тип в его объявлении метода.User
. Важное различие, потому что это означает, что класс User нужно только объявить в этой точке, а не определить . Но см. Обширный пост GMan.User
тип еще не объявлен.Вам необходимо определить MyMessageBox перед пользователем, потому что пользователь включает объект MyMessageBox по значению (и поэтому компилятор должен знать его размер).
Также вам нужно будет переслать объявление User до MyMessageBox, потому что MyMessageBox включает члена типа User *.
источник
По теме, если у вас были:
Тогда это также сработает, потому что Пользователь определен в MyMessageBox как указатель
источник
Вы должны объявить его прототип перед его использованием:
изменить : поменял местами типы
источник
В C ++ всегда рекомендуется использовать один класс для каждого файла заголовка, см. Это обсуждение в SO [ 1 ]. Ответ GManNickG рассказывает, почему это произошло. Но лучший способ решить эту проблему - поместить
User
класс в один файл заголовка (User.h
), аMyMessageBox
класс в другой файл заголовка (MyMessageBox.h
). Потом в свойUser.h
включаешьMyMessageBox.h
и вMyMessageBox.h
включаешьUser.h
. Не забудьте «включить gaurds» [ 2 ], чтобы ваш код успешно компилировался.источник