@radionnazmiev
Self-taught alien

Первая попытка в ООП. Прошу оценить код. Что можно было бы исправить?

//Попробуйте программно смоделировать разговор людей.Всего есть 3 людей.Каждый человек имеет имя(строку) и возраст(число).
//Возраст каждого человека генерируется рандомно из диапазона от 20 до 40, а имена состоят из следующего списка(могут повторяться) : 
//Александр, Андрей, Анастасия, Ирина, Наталья, Павел, Роман, Светлана, Сергей, Татьяна.
//Любой человек способен выполнять два действия :
//-здороваться с другим человеком;
//-рассказывать о себе.
//Люди делятся на 3 типа(разные классы) :
//    Тип №1 : Формалисты.Здороваются со всеми следующим образом : Здравствуйте, <имя>!, где <имя> — это имя человека, с которым он здоровается.
//    Тип №2 : Неформалы.Со всеми здороваются : Привет, <имя>!.
//    Тип №3 : Реалисты.Если возраст собеседника меньше / равен или не больше, чем на 5 лет, то здороваются следующим образом : Привет, <имя>!, в противном случае — Здравствуйте, <имя>!.
//    В программной реализации приветствие должно быть реализовано как полиморфный метод, принимающий человека в качестве параметра и возвращающий строку.
//    Рассказ о человеке является строкой формата "Меня зовут Вася, мой возраст 21 лет и я неформал" (вместо Вася используется имя любого другого человека, 
//    вместо 21 возраст этого человека, вместо неформал может быть формалист, либо реалист).Как видите у людей с грамматикой не всё в порядке, 
//    и они говорят лет после любого числа — непорядок, это нужно обязательно исправить.
//    Программа должна показать информацию обо всех людях.Затем все люди должны поздороваться друг с другом в следующем порядке : 
//    первый здоровается со вторым, затем второй с первым, а затем первый с третьим, третий с первым и т.д.Например :
//    Петя : Привет, Вася!
//    Вася : Здравствуйте, Петя!
//    Петя : Привет, Женя!
//    Женя : Привет, Петя!


#include <iostream>
#include <cstdlib>   // для функций выбора случайного числа srand() и rand()
#include <ctime>     // чтобы в randomize опираться на время запуска программы
#include <vector>
#include <Windows.h> 
#include <conio.h>
#include <random>

using namespace std;

class Person
{
protected:
    static constexpr const char* const s_nameList[10] = { "Александр","Андрей","Анастасия","Ирина","Наталья","Павел","Роман","Светлана","Сергей","Татьяна" };
    const char* name = nullptr;
    int age;
    enum class Type
    {
        FORMALIST = 0,
        NEFORMAL,
        REALIST,
        MAX_TYPE
    };
    Type type;
public:
    Person()
    {
        age = getRandomNumber(20, 40);
        name = s_nameList[getRandomNumber(0, 9)];
        type = static_cast<Type>(getRandomNumber(0, 2));
    };
    virtual void greetAPerson(const Person* person) const = 0;
    virtual void tellAboutMyself() const = 0;
    const char* returnMyTypeInText() const
    {
        switch (type)
        {
        case Type::FORMALIST:
            return "формалист";
            break;
        case Type::NEFORMAL:
            return "неформал";
            break;
        case Type::REALIST:
            return "реалист";
            break;
        default:
            return "MAX_TYPE";
            break;
        }
    };
    const char* getName() const
    {
        return name;
    };
    int getAge() const
    {
        return age;
    };
    virtual ~Person()
    {
    };
};

class Formalist : public Person
{
public:
    Formalist() : Person()
    {
        type = Type::FORMALIST;
    }
    virtual void greetAPerson(const Person* person) const override
    {
        cout << "Здравствуйте, " << person->getName() << "!\n";
    };
    virtual void tellAboutMyself() const override
    {
        cout << "Меня зовут " << name << ", мой возраст " << age << " лет и я " << returnMyTypeInText() << "!" << endl;
        cout << endl;
    };
};

class Neformal : public Person
{
public:
    Neformal() : Person()
    {
        type = Type::NEFORMAL;
    }
    virtual void greetAPerson(const Person* person) const override
    {
        cout << "Привет, " << person->getName() << "!" << endl;
    };
    virtual void tellAboutMyself() const override
    {
        cout << "Меня зовут " << name << ", мой возраст " << age << " лет и я " << returnMyTypeInText() << "!" << endl;
        cout << endl;
    };
};

class Realist : public Person
{
public:
    Realist() : Person()
    {
        type = Type::REALIST;
    }
    virtual void greetAPerson(const Person* person) const override
    {
        if ((person->getAge() - age) >= 5)
        {
            cout << "Здравствуйте, " << person->getName() << "!" << endl;
        }
        else
        {
            cout << "Привет, " << person->getName() << "!" << endl;
        }
    };
    virtual void tellAboutMyself() const override
    {
        cout << "Меня зовут " << name << ", мой возраст " << age << " лет и я " << returnMyTypeInText() << "!" << endl;
        cout << endl;
    };
};

Person* createARandPers()
{
    switch (getRandomNumber(1, 3))
    {
    case 1:
        return new Formalist();
        break;
    case 2:
        return new Neformal();
        break;
    case 3:
        return new Realist();
        break;
    };
};

void filloutAnArr(vector<Person*>& arr)
{
    arr.resize(3);  
    for (auto& person : arr)
    {
        person = createARandPers();
    }
};

void introUrself(vector<Person*>& arr)
{
    for (auto& person : arr)
    {
        cout << person->getName() << ":" << endl;
        person->tellAboutMyself();
    }
};

void greetEachOther(vector<Person*>& arr)
{
    for (int i = 0; i < arr.size(); ++i)      // Объекты "приветствуют" друг друга;
    {
        for (int j = i + 1; j < arr.size(); ++j)
        {
            cout << arr[i]->getName() << ":\n";
            arr[i]->greetAPerson(arr[j]);
            cout << arr[j]->getName() << ":\n";
            arr[j]->greetAPerson(arr[i]);
            cout << endl;
        }
    }
};

int getRandomNumber(int min, int max)
{
    random_device rd;  //Will be used to obtain a seed for the random number engine
    mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
    uniform_int_distribution<int> distrib(min, max);
    return distrib(gen);
}

int main()
{
    srand(time(nullptr));
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    vector<Person*> array;
    filloutAnArr(array);
    introUrself(array);
    greetEachOther(array);
    for (auto each_person_pointer : array)
    {
        delete each_person_pointer;
    };
    _getch();
    return 0;
}
  • Вопрос задан
  • 186 просмотров
Пригласить эксперта
Ответы на вопрос 2
maaGames
@maaGames
Погроммирую программы
returnMyTypeInText() сделать виртуальной, чтобы каждый класс возвращал своё название. Потому что switch по типам не объектно-ориентировано :)
Про виртуальный деструктор не забыли, так что уже отлично для первого раза.
Лучше сразу приучаться разделять интерфейс и реализацию (h/cpp) и не писать using namespace std хэдере.
Ответ написан
Во-первых, программу стоит переписать без использования сырых указателей. Вместо них — std::string и std::unique_ptr<Person>. Создать указатель на наследника можно так:
static_cast<std::unique_ptr<Person>>(std::make_unique<Formalist>())


Во-вторых, присоединяюсь к maaGames, Type выкинуть, а для получения информации, специфичной для наследника, использовать виртуальные функции.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы