Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/21: Рейтинг темы: голосов - 21, средняя оценка - 4.57
45 / 2 / 0
Регистрация: 24.05.2018
Сообщений: 30
1

Хранение в контейнере указателей на объекты класса

24.04.2019, 09:18. Показов 3849. Ответов 3

Author24 — интернет-сервис помощи студентам
Здравствуйте, очень прошу помочь разобраться:
У меня есть учебная задача:

Есть компания, у компании могут быть сотрудники. Сотрудник характеризуется именем, датой поступления на работу, базовой ставкой.
Сотрудники бывают 3 видов - Employee, Manager, Sales. У каждого сотрудника может быть начальник. У каждого сотрудника кроме Employee могут быть подчинённые.
1. Зарплата сотрудника Employee - это базовая ставка плюс 3% за каждый год работы в компании, но не больше 30% суммарной надбавки
2. Зарплата сотрудника Manager - это базовая ставка плюс 5% за каждый год работы в компании (но не больше 40% суммарной надбавки за стаж работы) плюс 0,5% зарплаты всех подчинённых первого уровня.
3. Зарплата сотрудника Sales - это базовая ставка плюс 1% за каждый год работы в компании (но не больше 35% суммарной надбавки за стаж работы) плюс 0,3% зарплаты всех подчинённых всех уровней.
4. У сотрудников (кроме Employee) может быть любое количество подчинённых любого вида.
Требуется: составить архитектуру классов, описывающих данную модель, а также реализовать алгоритм расчета зарплаты каждого сотрудника на произвольный момент времени, а также подсчёт суммарной зарплаты всех сотрудников фирмы в целом.
Замечание: при реализации тестового задания необходимо предположить, что вы разрабатываете не просто быстрый прототип программы, а систему enterprise уровня, соответственно важнее продемонстрировать архитектурно более красивое решение (пусть даже в данном случае это повредит быстродействию). Не обязательно реализовывать всю архитектуру в полном объёме, не реализованные или упрощённые моменты нужно прокомментировать.
Я хочу решить ее без использования баз данных, так как пока совсем не разбираюсь в них.

У меня была мысль сделать класс Компания, через этот класс взаимодействовать с пользователем:
-добавлять новых сотрудников, и их подчиненных
-удалять сотрудников
-запрашивать список всех подчиненных конкретного сотрудника,
-запрашивать зарплату конкретного сотрудника и его подчиненных или зарплату всех сотрудников компании.

И сделать 3 класса сотрудников: Employee (базовый), Manager, Sales

В классе Компания я хотела хранить (в set) созданные объекты сотрудников, а в объектах сотрудников - хранить указатели или итераторы на его подчиненных.

Попыталась сделать через shared_ptr (чтобы можно было хранить всех сотрудников в одном контейнере), и добавляя эти объекты - сохранять итератор, который возвращает метод insert и передавать этот итератор "начальнику", но так программа даже не компилируется.

Потом я создала 3 дека (для Employee, Manager, Sales) в классе Компания, туда при добавлении сотрудника вставляла созданный объект, а "начальнику" добавляла указатель на этот объект в деке, программа стала компилироваться, но не работает((

У меня есть код, но он совсем пока некрасивый, пожалуйста, не ругайтесь, сама знаю что он ужасен
Классы сотрудников будут внутри класса компании, поэтому поля public
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
class Employee {
public:
    const string name;
    const Date date_of_employment;
    const double base_salary;
    vector <Employee*> subordinate;
 
    friend ostream& operator << (ostream& os, const Employee& employee);
 
    Employee (const string& name, const Date& date,
              double salary) : name(name), date_of_employment(date),
              base_salary(salary) {}
    virtual ~Employee () {
        //--id;
    }
    virtual pair <double, double> GetSalary (const Date& date) const {
        if (date < date_of_employment) {
            return {0, 0};
        } else {
            double max_loyalty = base_salary * 0.3;
            double loyalty = (date - date_of_employment) * base_salary * 0.03;
            double result = base_salary +
                    (loyalty > max_loyalty ? max_loyalty : loyalty);
            return {result, result};
        }
    }
};
 
class Manager : public Employee {
public:
    double max_persent = 0.4;
public:
    Manager (const string& name, const Date& date,
              double salary) : Employee (name, date, salary)  {}
 
   virtual pair <double, double> GetSalary (const Date& date) const override {
        if (date < date_of_employment) {
            return {0, 0};
        } else {
            double max_loyalty = base_salary * 0.4;
            double loyalty = (date - date_of_employment) * base_salary * 0.05;
            double result = base_salary +
                    (loyalty > max_loyalty ? max_loyalty : loyalty);
            double all_salary = 0;
            for (const auto& i : subordinate) {
                auto p = i->GetSalary (date);
                result += p.first * 0.005;
                all_salary += p.second;
            }
            all_salary += result;
            return {result, all_salary};
        }
    }
    virtual void AddSubordinate (Employee* subordinate_) {
        subordinate.push_back(subordinate_);
    }
    virtual void RemoveSubordinate (Employee* subordinate_) {
        auto it = find(subordinate.begin(), subordinate.end(), subordinate_);
        if (it != subordinate.end()) {
        subordinate.erase(it);
        }
    }
    virtual void ShowSubordinate (ostream& os, const Date& date) const {
 
            if (subordinate.empty()) {
                os << "The employee " << this->name << " has no subordinates!\n";
            } else {
                for (const auto& i : subordinate) {
                    os << this->name << i;
                }
            }
        }
 
 
 
 
};
 
class Sales : public Manager {
public:
    double max_persent = 0.35;
    Sales (const string& name, const Date& date,
              double salary) : Manager (name, date, salary) {}
    pair <double, double> GetSalary (const Date& date) const override {
        if (date < date_of_employment) {
            return {0, 0};
        } else {
            double max_loyalty = base_salary * 0.35;
            double loyalty = (date - date_of_employment) * base_salary * 0.01;
            double result = base_salary +
                    (loyalty > max_loyalty ? max_loyalty : loyalty);
            double all_salary = 0;
            for (const auto& i : subordinate) {
                auto p = i->GetSalary (date);
                all_salary += p.second;
            }
            result += all_salary * 0.003;
            return {result, all_salary};
        }
    }
 
};
ostream& operator << (ostream& os, const Employee& employee) {
    os << " NAME: " << employee.name << " DATE OF EMPLOYMENT: " <<
    employee.date_of_employment << " BASE SALARY: " << employee.base_salary << '\n';
        return os;
}
в другом файле:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
enum class Employees {
    EMPLOYEE,
    MANAGER,
    SALES,
};
 
class Company {
private:
 deque <Employee> employees;
 deque <Manager> managers;
 deque <Sales> sales;
   // deque <shared_ptr<Employee>> employees;
 const string name;
public:
 
    Company (const string& name) : name(name) {}
    template <typename Container>
    void AddSubordinate (Container& c, Employee* empl, const string& chief_name) {
        if (!(chief_name.empty())) {
        for (auto& i : c) {
 
            if (i.name == chief_name) {
                i.subordinate.push_back(empl);
                break;
            }
        }
    }
}
    void AddEmployee (const string& name, const Date& date,
                      double salary, Employees employee_type,
                      const string& chief_name = "") {
        if (employee_type == Employees::EMPLOYEE) {
            employees.push_back({name, date, salary});
            AddSubordinate (employees, &employees[employees.size()-1], chief_name);
        } else if (employee_type == Employees::MANAGER) {
            managers.push_back({name, date, salary});
            AddSubordinate (managers, &managers[managers.size()-1], chief_name);
        } else {
            sales.push_back({name, date, salary});
            AddSubordinate (sales, &sales[sales.size()-1], chief_name);
        }
      }
       void ShowSubordinate (ostream& os, const string& name, const Date& date) const {
            auto it = find_if(managers.begin(), managers.end(), [name] (const Employee& e) {
                           return (name == e.name);});
            if (it != managers.end()) {
                (*it).ShowSubordinate(os, date);
            }
        }
 
};
Вопрос: можно ли сделать так как я задумала: в "Начальнике" хранить указатели на его подчиненных - если можно, то подскажите, пожалуйста как,
или надо полностью менять подход? Тогда, пожалуйста намекните на что обратить внимание.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.04.2019, 09:18
Ответы с готовыми решениями:

Вектор указателей на объекты класса
Добрый вечер! Есть базовый класс Place от него наследуется класс City. Мне нужно реализовать...

Динамический массив указателей на объекты класса
Добрый вечер! Нужна помощь У меня имеется класс STROKA(вроде уже готовый,и все хорошо) Только...

Массивы указателей на объекты как данные класса
Вообщем: мне надо так,чтобы объект имел связь с N-ым количеством каких-то объектов.про динамические...

Создать массив указателей на объекты класса, описывающего насекомых
Создать массив указателей на объекты класса, описывающего насекомых (количество ног, наличие...

3
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
24.04.2019, 10:05 2
Лучший ответ Сообщение было отмечено Nolwelin как решение

Решение

Nolwelin, я не смогу ответить достаточно объёмно так как у Вас довольно обширная задача с использованием паттернов. Тут просматривается фасад, стратегия, фабрика и возможно другие. Я попробую ответить на вот этот момент:
Цитата Сообщение от Nolwelin Посмотреть сообщение
В классе Компания я хотела хранить (в set) созданные объекты сотрудников, а в объектах сотрудников - хранить указатели или итераторы на его подчиненных.
Боюсь что не set ни vector ни какой-либо иной контейнер кроме списка (list например) не подойдут для хранения их итераторов. Только список сохраняет валидность итераторов при удалении/добавлении. О хранении указателей внутрь контейнера я посоветовал бы забыть. Особенно это касается множества и словаря/карты. Любое прямое изменение в члене данных множества может его испортить.
Но даже если хранилищем избрать список, то придётся повозиться с обеспечением доступа и обеспечением идиомы владения.
Посмотрите из любопытства в моём блоге 1,2,3,4,5...
Простой путь -
Цитата Сообщение от Nolwelin Посмотреть сообщение
в "Начальнике" хранить указатели на его подчиненных
Лучше контейнер. Вектор указателей. Поскольку моделировать прямые отношения между сотрудниками в Вашей задаче не нужно, то доступ через начальников подойдёт. Имейте в виду, что у начальника фирмы другие начальники в подчинённых. Указатели - смартпойнтеры или даже сырые (будете воевать с прямым выделением/освобождением). Каждый сотрудник должен уметь подсчитать свою зарплату. И каждый сотрудник должен уметь выполнять групповые операции над контейнером подчинённых (например предоставлять различные списки сотрудников, предоставлять их общую зарплату и т.п.). Получится этакое дерево.

Добавлено через 5 минут
ps каждый сотрудник (не только начальник) содержит указатель на список подчинённых. У работников (листьев) он нулевой.
1
45 / 2 / 0
Регистрация: 24.05.2018
Сообщений: 30
25.04.2019, 10:33  [ТС] 3
IGPIGP, спасибо, навели на мысль программа работает
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
25.04.2019, 10:52 4
Цитата Сообщение от Nolwelin Посмотреть сообщение
IGPIGP, спасибо, навели на мысль
Рад что Вы правильно восприняли мои сентенции. Тут важен общий подход. В конце концов можно указатель спрятать в Pimpl под завесой хост-класса (главного класса - пользователя стратегий) и реализовать идиому значения для полиморфного типа. Тогда контейнер может использовать значения. В общем, свобода и творчество. Удачи.
1
25.04.2019, 10:52
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.04.2019, 10:52
Помогаю со студенческими работами здесь

Можно ли динамически выделить память под массив указателей, на объекты класса?
Прошу прощения если не правильно назвал вопрос. Не знаю как правильно сформулировать. Можно ли...

Почему в сортировке указателей на объекты в вызове функции используются адреса объектов, а не указателей?
Доброго времени суток! Рассматриваю пример (из Лафоре) сортировки массива указателей на объекты,...

Хранение сложных классов в контейнере
Всем, привет. Прошу помощи в одной проблемке. В общем у нас должны быть два контейнера. Один...

Хранение в контейнере обьектов разных классов
Здраствуйте. Есть небольшая иерархия классов, в вершине которой стоит абстрактный класс vehicle, а...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru