简体   繁体   English

我可以从构造函数中传递成员函数指针吗?

[英]Can I pass a member function pointer from within a constructor?

Knowing how things roll around here somebody is gonna mark this "dupe" right away I'm sure but I sure can't find a good example for "passing member function from constructor".知道事情是如何在这里发生的,有人会立即标记这个“骗子”,但我肯定找不到“构造函数传递成员函数”的好例子。 Plenty of passing TO constructors or passing member functions outside, but not from inside a constructor...大量传递给构造函数或在外部传递成员函数,但不是从构造函数内部传递......

Story: We are using a library that uses 'mailboxes', and provides a hook for RX interrupt callbacks.故事:我们正在使用一个使用“邮箱”的库,并为 RX 中断回调提供了一个钩子。 We have our own class for devices.我们有自己的设备类。 Each object-instance needs to be able to handle one of the libraries mailboxes.每个对象实例都需要能够处理库邮箱之一。 Therefore constructor takes a mailbox (maybe > 1 in future), and then registers itself with the comms library.因此构造函数接受一个邮箱(将来可能> 1),然后将自己注册到 comms 库。

Simply: I want each objects constructor to pass a pointer to its "Handler" member function to this library.简单地说:我希望每个对象构造函数都将指向它的“处理程序”成员函数的指针传递给这个库。

The problem is of course with member functions vs. standard function pointers.问题当然是成员函数与标准函数指针。 Standard function pointer works fine, a static class function 'works' but we need to work with local object variables not static class variables.标准函数指针工作正常,静态类函数“工作”,但我们需要使用局部对象变量而不是静态类变量。

I have read a million threads on this and see the problems between member functions with hidden 'this' arguments vs standard C function pointers etc. etc.我已经阅读了一百万个线程,并看到了带有隐藏“this”参数的成员函数与标准 C 函数指针等之间的问题。

Have attempted to use lambda and std::function<> approaches... Maybe I am fighting the impossible?曾尝试使用 lambda 和 std::function<> 方法......也许我正在与不可能的事情作斗争? Is it impossible to pass a pointer to a function before the constructor completes creating the instance?在构造函数完成创建实例之前,是否不可能将指针传递给函数?

Example... (there is also a Class hierarchy for code-reuse purposes and there will be some function overrides and extensions in subclasses, but the basic mailbox setup should be in the top base class)示例...(还有一个用于代码重用目的的类层次结构,子类中会有一些函数覆盖和扩展,但基本的邮箱设置应该在顶级基类中)


class Base // Object that processes received communication frames
{
public: 
    Base(int);
    bool Initialized;
protected:
    fooframestruct rxframe;
    bool newframe;
    void Handler(const fooframestruct&);
    void DoOtherStuff();
};

Base::Base(int rxmailbox) : 
    Initialized(false),
    newframe(false)
{
    // point comms library to instance function when data received by its mailbox
    somelibraryobject.OnReceive(rxmailbox, this->Handler);  // obviously doesn't work cuz member func
}

void Base::Handler(const fooframestruct &thisframe)
{
    // callback function - just grab the frame and set a flag
    rxframe = thisframe;
    newframe = true;
}

void Base::DoOtherStuff()
{
    cout << "blah";
    Initialized = true;
}

class SubClass : Base
{
public:
    using Base:Base;
    void ExtendWithOtherStuff();
}   


main 
{

Base device1 = new Base(1);
Base device2 = new Base(7);
SubClass device3 = new Base(5);

// etc. 

}

Naturally compiler failure, invalid use of non-static member function, which as described above, I fully understand why, just not what the best way forwared is.自然编译器失败,非静态成员函数的无效使用,如上所述,我完全理解为什么,只是不是最好的方法是什么。

I realize I could do things like create a secondary class function say我意识到我可以做一些事情,比如创建一个二级类函数说

Base.RegisterMB() 

and then call that in the main setup such like:然后在主设置中调用它,例如:

Base device1 = new Base(1);
device1.RegisterMB();

But I hate the '2 step object init'.但我讨厌“两步对象初始化”。 I suppose a 3rd workaround would be setting the library up outside the Class aka...我想第三个解决方法是在类之外设置库,也就是......

somelibraryobject.OnReceive(rxmailbox, device1.Handler); 

or at least something like that , but again, I'd rather encapsulate the object setup if possible.或者至少是类似的东西,但同样,如果可能的话,我宁愿封装对象设置。

But maybe I can't?但也许我不能?

Member functions require instance of object to be invoked.成员函数需要调用对象的实例。 While standard components offer ways to do so, none lead to production of function pointer.虽然标准组件提供了这样做的方法,但没有一个会导致函数指针的产生。

In this particular case you can return address only to a static or global function, or captureless lambda.If you have to "capture" state of your object, you have devise such mechanism yourself.在这种特殊情况下,您只能将地址返回给静态或全局函数,或无捕获的 lambda。如果您必须“捕获”对象的状态,则您自己设计了这种机制。 Eg you may have factory\\pool\\manager which can allow to query existing object based on some parameter, passing pointer in parameters (visitor pattern?) and such.例如,您可能拥有 factory\\pool\\manager,它可以允许基于某个参数查询现有对象,在参数中传递指针(访问者模式?)等等。

The answer to the question is: no.问题的答案是:不。

  1. Create a static function that gets registered exactly once.创建一个只注册一次的静态函数。
  2. Create a static list in your class that registers each instance in that list.在您的类中创建一个静态列表,用于注册该列表中的每个实例。 Have it de-register each instance on that instance's destruction.让它在每个实例销毁时取消注册该实例。
  3. When that static function gets called have it call each instance with the relevant function.当该静态函数被调用时,让它使用相关函数调用每个实例。

Worst case is you have no instances and the static function gets called and has nothing to do.最坏的情况是你没有实例,静态函数被调用而无关紧要。

Can you make somelibraryobject.OnReceive() accept your callback routine as a std::function ?你能让somelibraryobject.OnReceive()接受你的回调例程作为std::function吗?

If so, you can use a capturing lambda to capture this , like so:如果是这样,您可以使用捕获 lambda 来捕获this ,如下所示:

somelibraryobject.OnReceive (rxmailbox, [this] mutable () { this->Handler (); });

Live demo现场演示

If Handler() is declared const , then you don't need the mutable .如果Handler()被声明为const ,那么你就不需要mutable

Basically answer is: NO can't do it inside a constructor , and, woefully C++-fighting-with-C painful to do it outside the constructor, resulting in just ugly bloated unreadable stupid code.基本上答案是:NO 不能在构造函数内部执行此操作,而且在构造函数外部执行此操作非常痛苦,导致 C++-fighting-with-C 痛苦,从而导致丑陋的臃肿不可读的愚蠢代码。

Outside of the constructor, in the main object setup, I also tried the std::bind approach outlined here: https://embeddedartistry.com/blog/2017/1/26/c11-improving-your-callback-game在构造函数之外,在主对象设置中,我还尝试了此处概述的 std::bind 方法: https : //embeddedartistry.com/blog/2017/1/26/c11-improving-your-callback-game

Client c;
register_callback(std::bind(&Client::func, &c, std::placeholders::_1));

(I should point out - same as suggested by Zaiborg from the start) But no love there either. (我应该指出 - 正如 Zaiborg 从一开始所建议的那样)但那里也没有爱。 no instance of overloaded function matches argument list.没有重载函数的实例与参数列表匹配。

More pain than value here... I'm going to just abandoned ability to use interrupt driven logic and have to clumsily poll for messages all the time.这里的痛苦多于价值......我将放弃使用中断驱动逻辑的能力,不得不一直笨拙地轮询消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获取指向类的复制构造函数的成员函数指针? - How can I obtain a member function pointer to the copy constructor of a class? 如何将成员函数传递给函数指针? - How Can I Pass a Member Function to a Function Pointer? 如何将成员 function 指针类型传递给模板? - How can I pass a member function pointer type to a template? 为什么我不能将this指针显式传递给成员函数? - Why can't I pass the this pointer explicitly to a member function? 构造函数中的成员函数指针 - member function pointer in constructor 如何在另一个类的静态成员函数中传递非静态成员函数的函数指针 - How can I pass function pointer of a non static member function in a static member function in another class 如何将成员函数指针传递给带有常规函数指针的函数? - How can I pass a member function pointer into a function that takes a regular function pointer? C++:为什么我可以将指针值成员变量从 const 成员函数传递给采用非 const 指针参数的外部函数? - C++: Why can I pass a pointer-valued member variable from a const member function to an external function taking a non const pointer parameter? 将没有复制构造函数的类的指向成员函数的指针传递到 Fortran - Pass pointer-to-member-function for class without copy constructor into Fortran 传递指向成员函数的指针 - To pass a pointer to a member function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM