Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.07.2017, 17:24   #1
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию Инициализация наследованного поля и проектирование иерархии для стратегии

Я строю такую иерархию классов:

Код:
class AbstractEmployee
{
public:
    virtual ~AbstractEmployee() = default;

protected:
    int          id;
    QString  firstname;
    QString  lastname;
    QDate    hire_date;
    double   base_rate;
    int          work_exp;
};

class Employee : public AbstractEmployee
{
public:
    Employee() = default;
    Employee(int id);

    void debug();
};
От общего класса AbstractEmployee наследуются три класса Employee, Manager и Sales. Когда в конструкторе класса Employee я хочу сделать так:

Код:
Employee::Employee
    :id(id)
{ }
компилятор сообщает, что переменная id не определена в классе. Почему? Ведь она наследуется. Или список инициализации инициализиирует только производную часть класса, а базовую часть производного класса должен иницализировать конструктор базового класса?

Как правильно определить этот конструктор?

Кроме того, в БД сотрудники трех типов имеют одни и те же поля, поэтому их надо инициализировать по одному алгоритму. Где определить этот алгоритм? В отдельной функции init() базового класса? В конструкторе базового класса?

Далее я пишу сервис для расчета зарплаты, внутри которого используется паттерн Стратегия. Как передавать сотрудников в метод calculate() стратегии? Как ссылки на баазовый класс?
Aoizora вне форума Ответить с цитированием
Старый 04.07.2017, 17:43   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от Aoizora Посмотреть сообщение
id не определена в классе. Почему? Ведь она наследуется
Наследуется, но определена не в этом классе.
Сделайте конструктор AbstractEmployee и передавайте id туда из конструктора Employee (и всех остальных).

Цитата:
Сообщение от Aoizora Посмотреть сообщение
сотрудники трех типов имеют одни и те же поля
Что делает бессмысленным использования трех разных классов.

Цитата:
Сообщение от Aoizora Посмотреть сообщение
Как передавать сотрудников в метод calculate() стратегии
Как ссылки на базовый класс. Если не придумаете какие методы должны быть виртуальными, то опять возникнет вопрос "зачем нужны разные классы".

Последний раз редактировалось waleri; 04.07.2017 в 17:47.
waleri вне форума Ответить с цитированием
Старый 04.07.2017, 18:10   #3
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию

>Что делает бессмысленным использования трех разных классов.

Мне нужно реализовать расчет зарплаты для сотрудников разных типов.

ЗП для Employee расчитывается просто, и формула расчета здесь не важна. ЗП для Manager и Sales расчитывается как маленький коэффициент (0.004 и 0.005), умноженный на суммарную зарплату всех его подчиненных. То есть для расчета ЗП, например, Manager, нужно вычислить его ЗП без прибавки, а затем подсчитать ЗП всех его подчиненных. Можно хранить в классе Manager список из всех его подчиненных, и у каждого вызвать метод вычисления ЗП при суммировании.

Итого расчет ЗП для Manager состоит из двух этапов:
1) Расчет ЗП без прибавки как для Employee
2) Расчет прибавки за подчиненных

Выглядит как вызов виртуального метода базового класса, который вычисляет ЗП без прибавки, и добавление к нему экстра ЗП от подчиненных. То есть в виртуальном методе расчета ЗП Manager вызывается виртуальный метод базового класса, а затем добавляется прибавка.

Сначала я выстроил линейную иерархию классов с виртуальными методами, но мне посоветовали писать сервис расчета ЗП со стратегией внутри. Вот и хочу разобраться.

>Как ссылки на базовый класс. Если не придумаете какие методы должны быть виртуальными, то опять возникнет вопрос "зачем нужны разные классы".

У меня вот такая ерунда:

Код:
class AbstractSalaryCalculator
{
public:
    virtual ~AbstractSalaryCalculator() = default;
    virtual double calculate(const AbstractEmployee& emp) = 0;
};

class EmployeeSalaryCalculator : public AbstractSalaryCalculator
{
public:
    double calculate(const AbstractEmployee& emp) override;
};

class ManagerSalaryCalculator : public AbstractSalaryCalculator
{
public:
    double calculate(const AbstractEmployee& emp) override;
};

class SalesSalaryCalculator : public AbstractSalaryCalculator
{
public:
    double calculate(const AbstractEmployee& emp) override;
};


class SalaryContext
{
public:
    virtual double calculate() = 0;
    virtual void setCalculator(AbstractSalaryCalculator * calc) = 0;

protected:
    AbstractSalaryCalculator * calculator;
};
В таком случае, как различать, какому методу будет передаваться проиизводный базового класса?
Aoizora вне форума Ответить с цитированием
Старый 04.07.2017, 18:28   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Вам тут больше pattern visitor подойдет.
https://en.wikipedia.org/wiki/Visitor_pattern

Если коротко, у AbstractSalaryCalculator есть три метода calculate - для каждого типа Employee.
У каждого Employee метод calculate будет вызывать нужный метод AbstractSalaryCalculator.

По сути, метод расчета у вас один, с разными параметрами - обычный employee это тот же менеджер, у которого коэффициент 1 и количество подчиненных 0

Самый простой способ, это вообще убрать AbstractSalaryCalculator и сделать просто calculate в каждом типе.
waleri вне форума Ответить с цитированием
Старый 04.07.2017, 20:19   #5
Aoizora
Заблокирован
 
Регистрация: 11.11.2016
Сообщений: 261
По умолчанию

>По сути, метод расчета у вас один, с разными параметрами - обычный employee это тот же менеджер, у которого коэффициент 1 и количество подчиненных 0

Да, верно. Я тоже заметил такое обобщение, но сложно придумать архитектуру, в которой это обобщение будет уместно.
Aoizora вне форума Ответить с цитированием
Старый 05.07.2017, 13:49   #6
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Код:

class AbstractEmployee
{
public:
    virtual ~AbstractEmployee() = default;

protected:
    int          id;
    QString  firstname;
    QString  lastname;
    QDate    hire_date;
    double   base_rate;
    int          work_exp;
    AbstractEmployee() = default;
    AbstractEmployee(int id):id(id){}
};

class Employee : public AbstractEmployee
{
public:
    Employee() = default;
    Employee(int id):AbstractEmployee(id){};

    void debug();
};
Или так, если не принципиально абстракта в конструкторе устанавливать (хотя, это лишает смысла все это наследование, как по мне):

Код:
class AbstractEmployee
{
public:
    virtual ~AbstractEmployee() = default;

protected:
    int          id;
    QString  firstname;
    QString  lastname;
    QDate    hire_date;
    double   base_rate;
    int          work_exp;
    AbstractEmployee() = default;
};

class Employee : public AbstractEmployee
{
public:
    Employee() = default;
    Employee(int id):AbstractEmployee()
    {
        this->id = id;
    };

    void debug();
};

Последний раз редактировалось alexzk; 05.07.2017 в 13:55.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Бот для онлайн стратегии ArtGrek Работа с сетью в Delphi 0 05.08.2014 13:59
Реализация выигрышной стратегии для компьютера makc56 Паскаль, Turbo Pascal, PascalABC.NET 13 18.05.2012 13:32
Инициализация статического поля ИВэТэшка Общие вопросы C/C++ 2 23.09.2011 10:52
движок для стратегии lamer69 Свободное общение 1 22.05.2011 01:16
Карта для стратегии sincemix Gamedev - cоздание игр: Unity, OpenGL, DirectX 5 21.07.2010 23:54