Попытка понять полиморфные классы с использованием std :: function с различными сигнатурами методов - PullRequest
0 голосов
/ 29 апреля 2018

Я довольно новичок и пытаюсь найти пример, который поможет мне понять полиморфизм, стирание типов и использование std :: function.

Я пытаюсь понять, создав этот пример класса, который может принимать базовое значение, а затем std :: function, которая затем является одной из многих математических операций над базовым значением.

double multiplyValue(double baseVal, double multiplyBy) {
    return baseVal * multiplyBy;
}

double divideValue(double baseVal, double divideBy) {
    return baseVal / divideBy;
}

double subtractFromDividedValue(double baseVal, double subtract, double divideBy) {
    return subtract - (baseVal / divideBy);
}

double inverseSubtract(double baseVal, double subtract) {
    return -(baseVal - subtract);
}

class PrintValue
{
public:
    PrintValue(int baseVal, std::function<double(double, double)> modifierFunc) {
        this->baseVal = baseVal;
        this->modifierFunc = modifierFunc;
    }

    void print() {
        std::cout << "Value : " << modifierFunc(baseVal, 2) << "\n";
    }

private:
    int baseVal;
    std::function<double(double, double)> modifierFunc;
};

int main()
{
    PrintValue multiplyVal(2, multiplyValue);
    multiplyVal.print(); 

    PrintValue divideVal(2, divideValue);
    divideVal.print();

    system("pause");
    return 0;
}

Мой класс PrintVal работает multiplyValue diverValue и inverseSubtract, потому что они имеют одинаковые сигнатуры методов - но когда я хочу, чтобы мой класс "PrintValue" мог принимать функцию subtractFromDividedValue ... это то, где я запутался!

Кроме того, я заметил, что я жестко закодировал «2» в качестве аргумента метода, передаваемого в modifierFunc в функции print ().

Я бы хотел иметь возможность динамически передавать переменное количество аргументов метода в класс, но я запутался здесь, потому что subtractFromDividedValue имеет больше параметров, чем другие математические функции. Поэтому я думаю, что мне просто нужно создать интерфейс и перегрузить класс для всех возможных перестановок аргументов, это правильно?

В конечном итоге мне просто нужен класс, в который я могу передать функцию, которая динамически изменяет «baseValue» ...

Приветствия

1 Ответ

0 голосов
/ 30 апреля 2018

Так что я думаю, что мне просто нужно создать интерфейс и перегрузить класс для всех возможных перестановок аргументов, это правильно?

Есть много способов, которыми вы могли бы это сделать, лучше всего попробовать и посмотреть, как они справляются - создайте новый вопрос здесь, если думаете, что что-то обещает, но вы застряли. В качестве примера одного из подходов вы могли бы заставить свой принтер работать в условиях baseVal для изменения, переменного количества параметров, предоставляемых с помощью vector, и функции для применения преобразования ...

PrintValue(double baseVal, std::vector<double> otherParameters, std::function<double(double, std::vector<double>)> modifierFunc)
  : baseVal_{baseVal}, otherParams_{std::move(otherParameters)}
{ }

... вы можете создавать подходящие функции, такие как ...

double subtractFromDividedValue(double baseVal, const std::vector<double>& params) {
    double subtract = params.at(0), divideBy = params.at(1);
    return subtract - (baseVal / divideBy);
}

Для большей гибкости вы можете добавить параметры при вызове print:

void print(const std::vector<double>& extraParams) {
    if (extraParams.size())
    {
        std::vector<double> allParams{ otherParams_.begin(), otherParams_.end() };
        for (double p : extraParams) 
            allParams.push_back(p);
        std::cout << "Value : " << modifierFunc(baseVal, allParams) << "\n";
    }
    else
        std::cout << "Value : " << modifierFunc(baseVal, otherParams_) << "\n";
}
...