Привет, можете подсказать, как можно лаконизировать этот код?

Рейтинг: -1Ответов: 2Опубликовано: 13.06.2023
#include <iostream>
#include <string>
using namespace std;
class Men
{
private:
    string name;
    string surname;
    float age;
public:
    void SetName(string name)   
    {
        this->name = name;
    }
    void SetSurname(string surname)
    {
        this->surname = surname;
    }
    void SetAge(int age)
    {
        this->age = age;
    }
    void printF()
    {
        cout << "Name: " << name << "\n" << "Surname: " << surname << "\n" << "Age: " << age << "\n";
    }
};
int main()
{
    Men people;
    string name; 
    cout << "Name: "; 
    cin >> name;
    string surname; 
    cout << "Surname: "; 
    cin >> surname; 
    int age;
    cout << "Age: ";
    cin >> age;
    people.SetName(name); 
    people.SetSurname(surname);
    people.SetAge(age);
    people.printF();

}

Ответы

▲ 6

Например, так:

#include <iostream>
#include <string>

using namespace std;

class Man
{
private:
    string name, surname;
    int age;
public:
    Man(const string& name, const string& surname, int age)
        :name(name),surname(surname),age(age){};

    friend ostream& operator << (ostream& os, const Man& m)
    {
        return os << "Name: " << m.name << "\nSurname: "
            << m.surname << "\nAge: " << m.age << "\n";
    }
};

int main()
{
    string name;
    cout << "Name: "; 
    cin >> name;
    string surname; 
    cout << "Surname: "; 
    cin >> surname; 
    int age;
    cout << "Age: ";
    cin >> age;

    Man people(name,surname,age);
    cout << people;
}
▲ 3

Ну поехали.

  • 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]] - больше выпендреж, на таких простеньких классах я бы его не писал.

Если уверены, что в сеттерах проверки не нужны - их смело в мусор вместе с геттерами, а поля сделать публичными.