如何在 C++ 中使用函数作为 class 的初始值设定项
How to use a function as an initializer for a class in C++
我正在尝试创建一个 class,它在初始化时接受一个函数作为参数。理想情况下,该功能应该已经存在。我知道在Python,我可以这样做:
class TestClass:
def __init__(self, function_parameter):
self.fp = function_parameter
def executeFP(self):
self.fp()
def testFunction():
print("test")
q = TestClass(testFunction)
q.executeFP()
我如何在 C++ 中执行此操作? (如果重要的话,我正在使用 Arduino)
您可以执行以下操作:
(不确定Arduino是否可以关注)
template <typename F>
class TestClass {
public:
TestClass( F func )
:m_func(func)
{
}
void executeFP()
{
m_func();
}
private:
F *m_func;
};
void doStuff()
{
std::cout << "test" << std::endl;
}
bool doAnotherStuff( )
{
std::cout <<"test " << 40 +2 << std::endl;
return true;
}
int main()
{
TestClass<decltype(doStuff)> someObj ( doStuff );
TestClass<decltype(doAnotherStuff)> someObj2 ( doAnotherStuff );
someObj.executeFP();
someObj2.executeFP();
}
见here
Arduino 没有 std::function
,因为 AVR GCC 不附带标准库,因此评论中的建议不适用于该特定平台。
如果您需要 Arduino 或其他嵌入式平台的类似行为,您可以使用 ETL 的 etl::function
或 etl::delegate
,或创建您自己的实现。 std::function
使用堆分配进行类型擦除,这通常不是嵌入式的好选择。
最简单的实现是使用 C 风格的函数指针:
// Generic definition of the function type
template <typename F>
class function;
// R: return type
// Args: Any arguments a function can take
template <typename R, typename... Args>
class function<R(Args...)> {
public:
// Type definition of the equivalent C function pointer
using function_type = R (*)(Args...);
// Default constructor: empty function.
// Never call the function while not initialized if using it this way.
function() = default;
// Constructor: store the function pointer
function(function_type f) : function_ptr(f){};
// Call operator: calls the function object like a normal function
// PS: This version does not do perfect forwarding.
R operator()(Args... args) { return function_ptr(args...); }
private:
function_type function_ptr;
};
// A helper function can be used to infer types!
template <typename R, typename... Args>
function<R(Args...)> make_function(R (*f)(Args...)) {
return {f};
}
Live example,有一些用例。
当然,您也可以只使用C 指针来处理这种情况,但是这个class 可以扩展到其他类型。如果您需要更复杂的行为,例如仿函数、成员函数和捕获 lambda,请参阅我上面引用的 ETL 实现。
我正在尝试创建一个 class,它在初始化时接受一个函数作为参数。理想情况下,该功能应该已经存在。我知道在Python,我可以这样做:
class TestClass:
def __init__(self, function_parameter):
self.fp = function_parameter
def executeFP(self):
self.fp()
def testFunction():
print("test")
q = TestClass(testFunction)
q.executeFP()
我如何在 C++ 中执行此操作? (如果重要的话,我正在使用 Arduino)
您可以执行以下操作: (不确定Arduino是否可以关注)
template <typename F>
class TestClass {
public:
TestClass( F func )
:m_func(func)
{
}
void executeFP()
{
m_func();
}
private:
F *m_func;
};
void doStuff()
{
std::cout << "test" << std::endl;
}
bool doAnotherStuff( )
{
std::cout <<"test " << 40 +2 << std::endl;
return true;
}
int main()
{
TestClass<decltype(doStuff)> someObj ( doStuff );
TestClass<decltype(doAnotherStuff)> someObj2 ( doAnotherStuff );
someObj.executeFP();
someObj2.executeFP();
}
见here
Arduino 没有 std::function
,因为 AVR GCC 不附带标准库,因此评论中的建议不适用于该特定平台。
如果您需要 Arduino 或其他嵌入式平台的类似行为,您可以使用 ETL 的 etl::function
或 etl::delegate
,或创建您自己的实现。 std::function
使用堆分配进行类型擦除,这通常不是嵌入式的好选择。
最简单的实现是使用 C 风格的函数指针:
// Generic definition of the function type
template <typename F>
class function;
// R: return type
// Args: Any arguments a function can take
template <typename R, typename... Args>
class function<R(Args...)> {
public:
// Type definition of the equivalent C function pointer
using function_type = R (*)(Args...);
// Default constructor: empty function.
// Never call the function while not initialized if using it this way.
function() = default;
// Constructor: store the function pointer
function(function_type f) : function_ptr(f){};
// Call operator: calls the function object like a normal function
// PS: This version does not do perfect forwarding.
R operator()(Args... args) { return function_ptr(args...); }
private:
function_type function_ptr;
};
// A helper function can be used to infer types!
template <typename R, typename... Args>
function<R(Args...)> make_function(R (*f)(Args...)) {
return {f};
}
Live example,有一些用例。
当然,您也可以只使用C 指针来处理这种情况,但是这个class 可以扩展到其他类型。如果您需要更复杂的行为,例如仿函数、成员函数和捕获 lambda,请参阅我上面引用的 ETL 实现。