首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何将类成员函数作为回调传递?

如何将类成员函数作为回调传递?
EN

Stack Overflow用户
提问于 2018-04-11 02:09:17
回答 2查看 0关注 0票数 0

我使用的API要求我将函数指针作为回调传递。我试图从我的类中使用这个API,但是我得到了编译错误。

下面是我从构造器中所做的工作:

代码语言:txt
复制
m_cRedundencyManager->Init(this->RedundencyManagerCallBack);

这不编译-我得到以下错误:

错误8错误C 3867:“CLoggersInfra::RedundencyManagerCallBack”:函数调用缺少参数列表;使用‘&CLoggersInfra::RedundencyManagerCallBack’创建指向成员的指针

我试着用这个建议&CLoggersInfra::RedundencyManagerCallBack-对我不起作用

对此有何建议或解释?

EN

回答 2

Stack Overflow用户

发布于 2018-04-11 11:00:08

正如现在展示的,init函数接受非会员功能。

代码语言:txt
复制
static void Callback(int other_arg, void * this_pointer) {
    CLoggersInfra * self = static_cast<CLoggersInfra*>(this_pointer);
    self->RedundencyManagerCallBack(other_arg);
}

调用Init

代码语言:txt
复制
m_cRedundencyManager->Init(&CLoggersInfra::Callback, this);

这是因为指向静态成员函数的函数指针不是成员函数指针,因此可以像指向空闲函数的指针一样处理。

票数 0
EN

Stack Overflow用户

发布于 2018-04-11 11:24:46

编译器建议使用&CLoggersInfra::RedundencyManagerCallBack是正确的。首先,如果RedundencyManagerCallBack是一个成员函数,则该函数本身不属于类CLoggersInfra的任何特定实例。它属于班级本身。如果以前调用过静态类函数,可能已经注意到使用了相同的SomeClass::SomeMemberFunction语法。由于函数本身是“静态”的,也就是说它属于类而不是特定实例,所以使用相同的语法。‘&’是必要的,因为从技术上讲,不直接传递函数--函数在C++中不是真实的对象。相反,正在技术上传递函数的内存地址,即指向函数指令从内存中开始的指针。但结果是一样的,你实际上是作为一个参数“传递一个函数”。

但在这种情况下,这只是问题的一半。正如我所说的,RedundencyManagerCallBack函数“不属于”任何特定实例。但是,听起来想要将它作为回调传递给特定的实例。要理解如何做到这一点,需要了解哪些成员函数是真正的:具有额外隐藏参数的任何类中的常规函数,而不是定义的函数。

例如:

代码语言:txt
复制
class A {
public:
    A() : data(0) {}
    void foo(int addToData) { this->data += addToData; }

    int data;
};

...

A an_a_object;
an_a_object.foo(5);
A::foo(&an_a_object, 5); // This is the same as the line above!
std::cout 
代码语言:txt
复制
struct A {
    int data;
};

void a_init(A* to_init)
{
    to_init->data = 0;
}

void a_foo(A* this, int addToData)
{ 
    this->data += addToData;
}

...

A an_a_object;
a_init(0); // Before constructor call was implicit
a_foo(&an_a_object, 5); // Used to be an_a_object.foo(5);

回到你的例子,现在有一个明显的问题。‘Init’需要一个指向接受一个参数的函数的指针。但是&CLoggersInfra::RedundencyManagerCallBack是一个指向接受两个参数的函数的指针,它是普通参数和秘密‘this’参数。因此,您仍然会得到编译器错误的原因(顺便提一句:如果您曾经使用过Python,这种混淆就是为什么所有成员函数都需要“Self”参数)。

处理这一问题的详细方法是创建一个特殊对象,该对象保存指向所需实例的指针,并具有一个名为“run”或“Execute”(或重载“()”操作符)之类的成员函数,该运算符接受成员函数的参数,并简单地使用存储实例上的这些参数调用成员函数。但这将要求您更改“Init”以接受您的特殊对象,而不是原始函数指针,这听起来像是其他人的代码。每当这个问题出现时,做一个特殊的类就会导致代码膨胀。

BIND::BIND将允许您获取一个函数,以及该函数的一个参数,并在该参数被“锁定”的地方创建一个新函数。因此,如果我有一个添加两个整数的函数,我可以使用Boost::BIND来创建一个新函数,其中一个参数锁定为5。这个新函数将只接受一个整数参数,并且总是将5具体添加到它。使用此技术,您可以“锁定”隐藏的“this”参数为特定的类实例,并生成一个只接受一个参数的新函数,就像您想要的那样(请注意,隐藏参数始终是第一参数之后,正常参数依次排列)。看看Boost::Binddocs的例子,他们甚至专门讨论如何将其用于成员函数。从技术上讲,这里有一个名为std::bind1的标准函数,您也可以使用它,但是Boost::BIND更通用。

当然,还有一个目标:Boost::BIND会为您提供一个很好的助推::函数,但从技术上讲,这仍然不是Init可能需要的原始函数指针。幸运的是,Boost提供了一种将Boost::Function的函数转换为原始指针的方法,如StackOverflow中所记录的那样。它如何实现这一点超出了这个答案的范围,尽管它也很有趣。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100003264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档