我可以从构造函数内传递会员函数指针吗?

Can I pass a member function pointer from within a constructor?

本文关键字:函数 指针 构造函数 我可以      更新时间:2023-10-16

知道事情如何在这里滚动,有人会立即标记这个" dupe",但我敢肯定找不到一个很好的示例构造函数"。大量传递构造函数或在外面传递成员功能,但不是从构造函数内部进行的...

故事:我们正在使用使用"邮箱"的库,并为RX中断回调提供了钩子。我们有自己的设备课程。每个对象启用都需要能够处理其中一个库邮箱。因此,构造函数取一个邮箱(将来可能是> 1个(,然后将其自身注册为COMMS库。

简单:我希望每个对象构造函数将指针传递给其"处理程序"成员函数到此库。

问题当然是成员函数与标准功能指针。标准功能指针正常工作,静态类功能"作品",但我们需要与本地对象变量而不是静态类变量一起工作。

我已经阅读了一百万个线程,并看到成员函数之间具有隐藏"此"参数与标准C函数指针等的问题等。

尝试使用lambda和std :: function<>接近...也许我正在与不可能的战斗?在构造函数完成创建实例之前,是否不可能将指针传递到函数?

示例...(也有一个类层次结构用于代码重新使用,并且子类中的一些功能覆盖和扩展,但是基本的邮箱设置应在顶级基类中(

(

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. 
}

自然的编译器故障,非静态成员函数的使用无效,如上所述,我完全理解了为什么,不是最好的方法是什么。

我意识到我可以做诸如创建二级函数

之类的事情
Base.RegisterMB() 

,然后在主设置中称之为:

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

,但我讨厌" 2步对象init"。我想第三个解决方法是将图书馆设置在班级之外...

somelibraryobject.OnReceive(rxmailbox, device1.Handler); 

或至少类似的东西,但是,如果可能的话,我宁愿封装对象设置。

但也许我不能?

成员函数需要调用对象的实例。尽管标准组件提供了这样做的方法,但没有任何导致功能指针的生产。

在这种特殊情况下,您只能将地址返回到静态或全局功能,也可以返回无限制的lambda。如果您必须"捕获"对象的状态,则自己就可以自己设计这种机制。例如。您可能有工厂 pool Manager,可以根据某些参数查询现有对象,将指针传递到参数(访问者模式?(等。

问题的答案是:否。

  1. 创建一个静态函数,该功能准确注册一次。
  2. 在您的类中创建一个静态列表,该列表在该列表中注册每个实例。让它在该实例的破坏上取消每个实例。
  3. 当调用该静态函数时,请使用使用相关函数调用每个实例。

最坏的情况是您没有实例,静态功能被调用,无关。

您可以让somelibraryobject.OnReceive()接受您的回调例程作为std::function

如果是这样,您可以使用捕获的lambda捕获this,例如:

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

实时演示

如果Handler()被声明为const,则您不需要mutable

基本上的答案是:否在构造函数中不能做,并且,c 痛苦地c - 在构造函数之外进行操作,导致丑陋的肿的不可读的愚蠢代码。

在构造函数之外,在主对象设置中,我还尝试了std :: bind方法:游戏

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

(我应该指出 - 与Zaiborg从一开始就建议(,但那里也不是爱。没有超载功能的实例匹配参数列表。

这里的痛苦比在这里更具价值...我将只是放弃使用中断驱动逻辑的能力,并且必须一直笨拙地进行调查。