Аватар для Nolwelin
45 / 2 / 0
Регистрация: 24.05.2018
Сообщений: 30

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

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

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

Есть компания, у компании могут быть сотрудники. Сотрудник характеризуется именем, датой поступления на работу, базовой ставкой.
Сотрудники бывают 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)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.04.2019, 09:18
Ответы с готовыми решениями:

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

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

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

3
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.04.2019, 10:05
Лучший ответ Сообщение было отмечено Nolwelin как решение

Решение

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

Добавлено через 5 минут
ps каждый сотрудник (не только начальник) содержит указатель на список подчинённых. У работников (листьев) он нулевой.
1
 Аватар для Nolwelin
45 / 2 / 0
Регистрация: 24.05.2018
Сообщений: 30
25.04.2019, 10:33  [ТС]
IGPIGP, спасибо, навели на мысль программа работает
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.04.2019, 10:52
Цитата Сообщение от Nolwelin Посмотреть сообщение
IGPIGP, спасибо, навели на мысль
Рад что Вы правильно восприняли мои сентенции. Тут важен общий подход. В конце концов можно указатель спрятать в Pimpl под завесой хост-класса (главного класса - пользователя стратегий) и реализовать идиому значения для полиморфного типа. Тогда контейнер может использовать значения. В общем, свобода и творчество. Удачи.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.04.2019, 10:52
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

Новые блоги и статьи
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru