如何在 C++ 中使用函数作为类的初始化程序 [重复]

Posted

技术标签:

【中文标题】如何在 C++ 中使用函数作为类的初始化程序 [重复]【英文标题】:How to use a function as an initializer for a class in C++ [duplicate] 【发布时间】:2019-08-19 03:30:34 【问题描述】:

我正在尝试创建一个在初始化时接受函数作为参数的类。理想情况下,该功能应该已经存在。我知道在 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)

【问题讨论】:

如果人们在这样做后解释为什么他们对帖子投了反对票,我会很高兴,只是反对票并不能告诉我任何事情 我猜可能有人对缺乏尝试不满意? @WeaktoEnumaElish 它不应该是一个匿名函数,它应该是一个已经存在的函数。 std::function 和模板方法都适用于现有函数。 您可能不应该尝试从 Arduino 代码 sn-ps SO答案中学习 C++。任何好的 C++ 书籍都应该以不止一种方式解释将函数作为参数传递。它确实是 C++ 的基础部分。 【参考方案1】:

Arduino 没有std::function,因为 AVR GCC 不附带标准库,因此 cmets 中的这些建议不适用于该特定平台。

如果您需要 Arduino 或其他嵌入式平台的类似行为,您可以使用ETL 的etl::functionetl::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 指针来处理这种情况,但是这个类可以扩展为其他类型。如果您需要更复杂的行为,例如仿函数、成员函数和捕获 lambda,请参阅我上面引用的 ETL 实现。

【讨论】:

我试图在我的课堂上实现这个,但它给出了一个错误,说“没有匹配函数调用'function::function()'”和一堆其他错误。看起来其中一些错误是因为我无法创建一个空函数(在 .h 文件中),但如果不这样做,我不确定如何使我的类的所有方法都可以访问该函数。我已将我的代码和所有编译器错误放在pastebin.com/K4Np4YHm。 @Merlin04 我的错。通过定义函数构造函数,我禁用了它的默认构造函数并且没有声明它回来。 Here 是您在 Arduino 编译器上编译的代码,在重新添加后没有错误。顺便说一句,对于这种特定情况,您不需要使用 make_function(如果您只需要 C 风格的函数,也不需要使用这个包装器)。 好的,如果我不需要使用这个包装器,我该怎么做? @Merlin04 如果你想在它上面实现额外的功能,这个包装器将是一个基础,比如我提到的 ETL 类。如果你只想使用不带参数的 void C 函数,你可以定义一个像 using function_type = void(*)() 这样的类型并在你的类中使用它。【参考方案2】:

您可以执行以下操作: (不确定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

【讨论】:

m_func(func) - 它们属于不同类型(F*F)... @Aconcagua foo 被声明为具有 F 类型,它实际上具有 F* 指针类型。虽然 decltype(doStuff) 的计算结果为 void () 而不是 void (*) ,但是该函数在 someObj ( doStuff ) 处可以隐式转换为指向自身的指针,因此没有错误。 嗯,好的,但随后就失去了与仿函数一起使用的资格。跳过与decltype(&amp;doStuff) 结合使用的指针可以避免这种情况(或者我们可以只推导出模板参数,如果 C++17 可用...)。

以上是关于如何在 C++ 中使用函数作为类的初始化程序 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C++:对象和类|| 类的构造函数与析构函数

C++:对象和类|| 类的构造函数与析构函数

在C++ 如何在堆中创建一个类的对象? 谢谢!

C++ 中类的构造函数理解

如何在 C++ 子类的构造函数中初始化超类的 const 成员变量?

如何在主函数的一个对象中初始化两个类的值? C++