Ну поехали.
using namespace std;
- плохо, как минимум потому что на первый взгляд перестает быть видно, где стандартные идентификаторы, а где ваши собственные.
Men
- опечатка. Это множественное число, в единственном должно быть Man
. Или Person
, чтобы не обвинили в сексизме, лол. Аналогично people
- тоже множественное число, должно быть person
.
На float age;
стоит добавить = 0
. Вообще, все поля класса лучше всегда инициализировать/занулять в теле класса (и вообще всегда инициализировать любые переменные), чтобы не ловить труднообнаружимые ошибки на неинициализированных переменных.
Недостает std::move
в сеттерах: this->name = std::move(name);
printF
:
Забыт const
: void printF() const {...}
Имя написано не в том стиле, что у других методов. Стоило выбрать PrintF
или вообще Print
(непонятно почему F
).
Прибито гвоздями к std::cout
- плохо, лучше принимать произвольный std::ostream
.
Возможно стоит переименовать в operator<<
, но тут как вам больше нравится.
Вообще, std::ostream
теряет в популярности, и дело идет к тому, что std::format
станет основным способом форматирования. Но пока его нормально не поддержали в libc++ (одной из трех популярных реализаций стандартной библиотеки С++), остается либо использоваться библиотекой libfmt (которая делает примерно то же самое), либо ждать. Плюс, непонятно, что тогда вместо std::cin
.
Странно, что из класса никак нельзя прочитать поля. Из-за этого им будет неудобно пользоваться.
Если печать сделана методом класса, то я бы считывание тоже встроил в класс.
Не хватает проверки на успешность считывания.
Обычно я бы советовал убрать сеттеры (и геттеры) и просто сделать поля публичными, потому что ваши сеттеры все равно не делают ничего интересного.
Но допустим в них можно было бы добавить какие-то проверки (на ум приходит проверка на age >= 0
).
В итоге получается так:
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
class Person
{
std::string name;
std::string surname;
float age = 0;
public:
Person() {} // Здесь ни на что не влияет, но наглядо.
[[nodiscard]] const std::string &GetName() const
{
return name;
}
void SetName(std::string name)
{
this->name = std::move(name);
}
[[nodiscard]] const std::string &GetSurname() const
{
return surname;
}
void SetSurname(std::string surname)
{
this->surname = std::move(surname);
}
[[nodiscard]] int GetAge() const
{
return age;
}
void SetAge(int age)
{
assert(age >= 0); // Для примера.
this->age = age;
}
};
// Не член по аналогии с `operator>>`.
std::ostream &operator<<(std::ostream &s, const Person &o)
{
return s << "Name: " << o.GetName() << "\n"
"Surname: " << o.GetSurname() << "\n"
"Age: " << o.GetAge() << "\n";
}
// Не член, чтобы не мог напрямую выставлять приватные поля обходя проверки,
// и должен был использовать сеттеры.
std::istream &operator>>(std::istream &s, Person &o)
{
std::string name;
s >> name;
o.SetName(std::move(name));
std::string surname;
s >> surname;
o.SetSurname(std::move(surname));
int age = 0;
s >> age;
o.SetAge(age);
return s;
}
int main()
{
Person person;
if (!(std::cin >> person))
{
std::cout << "Unable to read a person.\n";
return 1;
}
std::cout << person;
}
Здесь [[nodiscard]]
- больше выпендреж, на таких простеньких классах я бы его не писал.
Если уверены, что в сеттерах проверки не нужны - их смело в мусор вместе с геттерами, а поля сделать публичными.