Я думаю, проблема в том, что вы смешиваете код C ++ с мышлением C.То, что вы действительно должны здесь делать, это использовать оператор извлечения opeartor>>()
вместе с потоками ввода-вывода C ++.Это в отличие от использования стандартного ввода-вывода C вместе с функцией read()
.Для записи объекта используйте оператор вставки operator<<()
вместо функции C write()
.
Для работы со строками используйте std::string
.Этот класс обеспечивает operator<<()
и operator>>()
.Таким образом, вы можете сказать std::string s
, а затем io << s
и io >> s
, где io
- это некоторый объект потока ввода-вывода C ++.Это будет делать правильную вещь (тм).Философия здесь заключается в том, что класс std::string
знает лучше, чем вы, пользователь, как сериализовать объект std::string
.Так что давайте сделаем это, используя операторы << и >>.
Продолжая эту идею, вы, как автор User
, лучше других знаете, как сериализовать объект User
,Поэтому предоставьте операторы << и >> для пользователей вашего класса в качестве услуги.«Пользователи вашего класса» вполне могут быть вами через неделю, когда вы полностью забыли, как правильно сериализовать объект User
.(Или вы думаете, что помните, но на практике вы забыли детали, что привело к ошибке в вашем коде).Пример:
// in User.h
#include <string>
#include <iosfwd> // forward declarations of standard IO streams
namespace mine {
class User {
User(const std::string& name) : username(name) { }
friend std::ostream& operator<<(std::ostream&, const User&);
friend std::istream& operator>>(std::istream&, User&);
private:
std::string username;
};
std::ostream& operator<<(std::ostream& out, const User& u)
{
return out << u.username;
}
std::istream& operator>>(std::istream& in, User& u)
{
return in >> u.username;
}
} // namespace mine
С этого момента, чтобы сохранить пользователя в файл, который вы говорите
std::ofstream f("filename");
User u("John");
f << u;
Вот и все.Чтобы прочитать пользователю:
std::ifstream f2("filename");
f2 >> u;
Хорошей практикой является перенос кода в пространство имен.Среды IDE дают хорошую визуализацию этой проблемы, показывая, сколько символов видно с помощью функции автозаполнения.Вы видите, насколько много беспорядка в глобальном масштабе.Оборачивая код в пространство имен, вы группируете его под именем области, сохраняя еще больше беспорядка в глобальной области имен.Это просто аккуратно.Если вы поместите свой код в свое собственное пространство имен, вы можете выбрать любое имя для функции, класса или переменной, если вы не выбрали его ранее.Если вы не поместите его в пространство имен, вам нужно поделиться именами с другими.Это похоже на скунса, объявляющего свою территорию, только без постельного запаха.
На этой ноте я предлагаю вам снять это using namespace std
с вашего заголовка.Это приводит все символы в пространстве имен std
в область действия всех файлов, которые #include
являются заголовками.Это плохая практика.Скажите, пожалуйста, using namespace std
в файлах реализации, но не в заголовочных файлах.
Конечно, некоторые скажут, что даже это плохая идея.Я лично думаю, что это хорошо, если вы знаете, что в этом конкретном файле реализации могут возникнуть конфликты имен.Но, по крайней мере, вы знаете, где находится оператор using
: он находится в вашем файле реализации и вызывает только конфликты в этом файле реализации.Это своего рода пистолет (пластиковый водяной пистолет, но, тем не менее, пистолет), только вы можете стрелять (мокрыми) собственными ногами, а не другими.Что, на мой взгляд, совершенно нормально.