Определение функции члена при построении объекта
У меня есть класс, в котором мне нужна функция, которую я могу определить для каждого объекта. Я хотел бы иметь возможность определять конкретные функции каждого объекта при определении вектора указанных объектов. Эти векторы моего объекта составят часть библиотеки. Вот неудачный пример того, что я пытаюсь сделать:
#include <iostream>
#include <vector>
class FunctionEater {
public:
virtual double func() {}
FunctionEater(double (*Func)) {
func = Func; // Not sure of the correct syntax here
}
};
std::vector<FunctionEater> gorgers {
{
double () { // Not sure of the syntax here, or if there is even syntax to do this
double result = 0.794 * 739.775;
return result;
}
},
{
double () {
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
}
}
}
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
Итак, две вещи, которые я пытаюсь выяснить или найти много документации, заключаются в следующем:
- Как определить функцию при определении элементов gorgers[]
- Как принять функцию, которую я передал конструктору как (*Func), и сохранить ее как виртуальный double func()
Я бы предпочел иметь возможность определить функцию в определении объекта. Я потратил немало времени на то, чтобы выяснить, как лучше всего написать свой вектор объектов, и способ, с которым наиболее визуально легко работать в этой ситуации, по-видимому, определяет каждый аспект каждого объекта в одном блоке при определении вектор, в котором они содержатся.
Я признаю, я также не знаю, правильно ли (* Func) при использовании виртуальной функции, но это адаптация с моей первой попытки с использованием указателей на функции. Я также рад принять альтернативные предложения, которые могут работать лучше, чем метод, который я пытаюсь использовать.
Заранее благодарим за любую помощь, которую вы можете предложить, и я с удовольствием отредактирую или обновлю мой вопрос, если это необходимо.
Пит
2 ответа
Что вы хотите, так это лучшая поддержка функциональных возможностей на вашем языке. К счастью, вы используете C++!
После C++11 у нас есть лямбды и std::function
объекты, которые представляют объекты полиморфной функции во время выполнения.
Лямбда определяется так:
auto yourSecondFunc = [](){
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
};
Я был ленив и использовал авто там, но на самом деле, мы могли бы назначить его на std::function
объект:
std::function<double()> yourSecondFunc = [](){
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
};
Тот std::function<double()>
означает, что функция не принимает аргументов и возвращает двойной. Однако обратите внимание, что тип лямбда не является std::function
объект, но это не место, чтобы обсудить это.
Таким образом, вы можете хранить std::function<double()>
в вашем FunctionEater
учебный класс:
class FunctionEater {
public:
std::function<double()> func;
FunctionEater(const std::function<double()>& f) {
func = f;
}
void callMe() { double res = func(); } // how a function object is used
};
Тогда ваш вектор становится таким:
std::vector<FunctionEater> gorgers {
FunctionEater { []()
{
double result = 0.794 * 739.775;
return result;
}
},
FunctionEater { []()
{
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
}
}
};
И ваш main
? Это на самом деле то же самое:
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
Правильный синтаксис:
#include <iostream>
#include <vector>
#include <functional>
struct FunctionEater
{
using Func = double (*)();
//using Func = std::function<double()>;
template<typename F>
FunctionEater(F f): func(f) {}
Func func;
};
std::vector<FunctionEater> const gorgers = {
[]{ return 0.794 * 739.775; },
[]{ return 0.794 * 739.775 + 0.62; }
};
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
Вы можете использовать любое определение Func
, Указатель на функцию имеет меньше накладных расходов, но он может работать только с лямбда без захвата. std::function
гораздо более гибкий.
NB. Я не уверен, почему инициализация вектора не работает без конструктора шаблона для FunctionEater, но я обнаружил, что в этом случае инициализаторы вектора должны быть явно преобразованы (либо в Func
или же FunctionEater
).