我使用的API要求我将函数指针作为回调传递。我试图从我的类中使用这个API,但是我得到了编译错误。
下面是我从构造器中所做的工作:
m_cRedundencyManager->Init(this->RedundencyManagerCallBack);
这不编译-我得到以下错误:
错误8错误C 3867:“CLoggersInfra::RedundencyManagerCallBack”:函数调用缺少参数列表;使用‘&CLoggersInfra::RedundencyManagerCallBack’创建指向成员的指针
我试着用这个建议&CLoggersInfra::RedundencyManagerCallBack
-对我不起作用
对此有何建议或解释?
发布于 2018-04-11 11:00:08
正如现在展示的,init函数接受非会员功能。
static void Callback(int other_arg, void * this_pointer) {
CLoggersInfra * self = static_cast<CLoggersInfra*>(this_pointer);
self->RedundencyManagerCallBack(other_arg);
}
调用Init
m_cRedundencyManager->Init(&CLoggersInfra::Callback, this);
这是因为指向静态成员函数的函数指针不是成员函数指针,因此可以像指向空闲函数的指针一样处理。
发布于 2018-04-11 11:24:46
编译器建议使用&CLoggersInfra::RedundencyManagerCallBack是正确的。首先,如果RedundencyManagerCallBack是一个成员函数,则该函数本身不属于类CLoggersInfra的任何特定实例。它属于班级本身。如果以前调用过静态类函数,可能已经注意到使用了相同的SomeClass::SomeMemberFunction语法。由于函数本身是“静态”的,也就是说它属于类而不是特定实例,所以使用相同的语法。‘&’是必要的,因为从技术上讲,不直接传递函数--函数在C++中不是真实的对象。相反,正在技术上传递函数的内存地址,即指向函数指令从内存中开始的指针。但结果是一样的,你实际上是作为一个参数“传递一个函数”。
但在这种情况下,这只是问题的一半。正如我所说的,RedundencyManagerCallBack函数“不属于”任何特定实例。但是,听起来想要将它作为回调传递给特定的实例。要理解如何做到这一点,需要了解哪些成员函数是真正的:具有额外隐藏参数的任何类中的常规函数,而不是定义的函数。
例如:
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
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中所记录的那样。它如何实现这一点超出了这个答案的范围,尽管它也很有趣。
https://stackoverflow.com/questions/-100003264
复制相似问题