如何在同一个class的函数中获取class成员的函数指针?
How to get the function pointer of a class member in a function of the same class?
我被这个难住了。
我有一个带有函数 DoTheThing1
的 class Foo
,它接受一个指向带有 0 个参数的 void 函数的指针并调用该函数。
class Foo {
public:
Foo () {}
void DoTheThing1 (void (*theThing)()) {
theThing();
}
};
我有另一个 class Bar
有一个 Foo
的实例。
Class Bar
也有自己的函数 DoTheThing2
,它尝试在其构造中将 DoTheThing2
的指针传递给 Foo's
DoTheThing1
.
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1(&Bar::DoTheThing2);
}
void DoTheThing2 () {
// Something happens.
}
};
我在传入函数指针的行收到此错误 error C2664: 'void Foo::DoTheThing1(void (__cdecl *)(void))': cannot convert argument 1 from 'void (__cdecl Bar::* )(void)' to 'void (__cdecl *)(void)
。
Bar () {
foo->DoTheThing1(&Bar::DoTheThing2); /// Does not like.
}
我不确定如何解决这个问题。似乎需要一些奇怪的演员表。
编辑
实际上,我的情况比仅从自身内部的 class 成员调用函数指针要复杂一些。我的代码实际上做的是将指针设置为一个变量,然后稍后调用它。
class Foo {
public:
void (*m_onEvent) ();
Foo () {}
void SetTheThing (void (*theThing)()) {
m_onEvent = theThing;
}
template <typename T>
void SetTheThing (T&& theThing) {
m_onEvent = theThing;
}
void DoTheThing1 () {
m_onEvent();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->SetTheThing([this](){ DoTheThing2(); }); // error C2440: '=': cannot convert from 'T' to 'void (__cdecl *)(void)'
foo->SetTheThing(&DoTheThing2); // '&' illegal operation on bound member function expression.
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
编辑
所以现在我正尝试使用 class 模板破解它,但我一直被这个错误阻止:Term does not evaluate to a function taking 0 arguments.
我正在尝试弄清楚我的函数指针为何不计算任何值。
template <typename U>
class Foo {
public:
void (U::*m_theThing) ();
Foo () {}
void SetTheThing (void (U::*theThing)()) {
m_theThing = theThing;
}
void DoTheThing1 () {
m_theThing(); // Term does not evaluate to a function taking 0 arguments.
}
};
class Bar {
public:
Foo<Bar>* foo = new Foo<Bar>();
Bar () {
foo->SetTheThing(&Bar::DoTheThing2);
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
&Bar::DoTheThing2
是成员函数指针,不是普通函数指针。因此错误。这是使用 lambdas 和 std::functional
:
的解决方法
#include <functional>
class Foo {
public:
Foo () {}
void DoTheThing1 (std::function<void()>& theThing) {
theThing();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1([this](){ DoTheThing2(); });
}
void DoTheThing2 () {
// Something happens.
}
};
如果 std::functional
被证明是瓶颈,您可以改用模板函数:
#include <functional>
class Foo {
public:
Foo () {}
template <typename Callable>
void DoTheThing1 (Callable&& theThing) {
theThing();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1([this](){ DoTheThing2(); });
}
void DoTheThing2 () {
// Something happens.
}
};
编辑:
如果要存储指向成员函数的指针,还需要该成员函数的实例 class 以便稍后调用它。以下是您可以如何修复您的示例:
#include <iostream>
template <typename U>
class Foo {
public:
void (U::*m_theThing) ();
U* m_u;
Foo (U* u): m_u{u} {}
void SetTheThing (void (U::*theThing)()) {
m_theThing = theThing;
}
void DoTheThing1 () {
(m_u->*m_theThing)(); // Works fine.
}
};
class Bar {
public:
Foo<Bar>* foo = new Foo<Bar>(this);
Bar () {
foo->SetTheThing(&Bar::DoTheThing2);
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
旧方法:您需要一个模板来获取 class 和函数的专业化。
工作示例:
#include <iostream>
//For member function of class C
template <typename C = void>
struct TheCaller
{
TheCaller() : theClass(nullptr), mf(nullptr) {}
C* theClass;
void (C::*mf)();
void SetTheThing(C* aClass, void (C::*memberFunction)())
{
theClass = aClass;
mf = memberFunction;
}
void CallTheThing()
{
if ( theClass )
(theClass->*mf)();
}
};
//Specialization for any function
template <>
struct TheCaller<void>
{
TheCaller() : mf(nullptr) {}
void (*mf)();
void SetTheThing(void (*memberFunction)())
{
mf = memberFunction;
}
void CallTheThing()
{
if ( mf )
mf();
}
};
struct Bar
{
void DoTheBarThing()
{ std::cout << "DoTheBarThing called" << std::endl; }
};
void AFunction()
{ std::cout << "AFunction called" << std::endl; }
int main()
{
TheCaller<Bar> foo;
Bar bar;
foo.SetTheThing(&bar, &Bar::DoTheBarThing);
foo.CallTheThing();
TheCaller<> foo2;
foo2.SetTheThing(&AFunction);
foo2.CallTheThing();
}
我被这个难住了。
我有一个带有函数 DoTheThing1
的 class Foo
,它接受一个指向带有 0 个参数的 void 函数的指针并调用该函数。
class Foo {
public:
Foo () {}
void DoTheThing1 (void (*theThing)()) {
theThing();
}
};
我有另一个 class Bar
有一个 Foo
的实例。
Class Bar
也有自己的函数 DoTheThing2
,它尝试在其构造中将 DoTheThing2
的指针传递给 Foo's
DoTheThing1
.
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1(&Bar::DoTheThing2);
}
void DoTheThing2 () {
// Something happens.
}
};
我在传入函数指针的行收到此错误 error C2664: 'void Foo::DoTheThing1(void (__cdecl *)(void))': cannot convert argument 1 from 'void (__cdecl Bar::* )(void)' to 'void (__cdecl *)(void)
。
Bar () {
foo->DoTheThing1(&Bar::DoTheThing2); /// Does not like.
}
我不确定如何解决这个问题。似乎需要一些奇怪的演员表。
编辑
实际上,我的情况比仅从自身内部的 class 成员调用函数指针要复杂一些。我的代码实际上做的是将指针设置为一个变量,然后稍后调用它。
class Foo {
public:
void (*m_onEvent) ();
Foo () {}
void SetTheThing (void (*theThing)()) {
m_onEvent = theThing;
}
template <typename T>
void SetTheThing (T&& theThing) {
m_onEvent = theThing;
}
void DoTheThing1 () {
m_onEvent();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->SetTheThing([this](){ DoTheThing2(); }); // error C2440: '=': cannot convert from 'T' to 'void (__cdecl *)(void)'
foo->SetTheThing(&DoTheThing2); // '&' illegal operation on bound member function expression.
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
编辑
所以现在我正尝试使用 class 模板破解它,但我一直被这个错误阻止:Term does not evaluate to a function taking 0 arguments.
我正在尝试弄清楚我的函数指针为何不计算任何值。
template <typename U>
class Foo {
public:
void (U::*m_theThing) ();
Foo () {}
void SetTheThing (void (U::*theThing)()) {
m_theThing = theThing;
}
void DoTheThing1 () {
m_theThing(); // Term does not evaluate to a function taking 0 arguments.
}
};
class Bar {
public:
Foo<Bar>* foo = new Foo<Bar>();
Bar () {
foo->SetTheThing(&Bar::DoTheThing2);
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
&Bar::DoTheThing2
是成员函数指针,不是普通函数指针。因此错误。这是使用 lambdas 和 std::functional
:
#include <functional>
class Foo {
public:
Foo () {}
void DoTheThing1 (std::function<void()>& theThing) {
theThing();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1([this](){ DoTheThing2(); });
}
void DoTheThing2 () {
// Something happens.
}
};
如果 std::functional
被证明是瓶颈,您可以改用模板函数:
#include <functional>
class Foo {
public:
Foo () {}
template <typename Callable>
void DoTheThing1 (Callable&& theThing) {
theThing();
}
};
class Bar {
public:
Foo* foo = new Foo();
Bar () {
foo->DoTheThing1([this](){ DoTheThing2(); });
}
void DoTheThing2 () {
// Something happens.
}
};
编辑:
如果要存储指向成员函数的指针,还需要该成员函数的实例 class 以便稍后调用它。以下是您可以如何修复您的示例:
#include <iostream>
template <typename U>
class Foo {
public:
void (U::*m_theThing) ();
U* m_u;
Foo (U* u): m_u{u} {}
void SetTheThing (void (U::*theThing)()) {
m_theThing = theThing;
}
void DoTheThing1 () {
(m_u->*m_theThing)(); // Works fine.
}
};
class Bar {
public:
Foo<Bar>* foo = new Foo<Bar>(this);
Bar () {
foo->SetTheThing(&Bar::DoTheThing2);
}
void DoTheThing2 () {
std::cout << "I did the thing." << std::endl;
}
};
int main () {
Bar* bar = new Bar();
bar->foo->DoTheThing1();
}
旧方法:您需要一个模板来获取 class 和函数的专业化。
工作示例:
#include <iostream>
//For member function of class C
template <typename C = void>
struct TheCaller
{
TheCaller() : theClass(nullptr), mf(nullptr) {}
C* theClass;
void (C::*mf)();
void SetTheThing(C* aClass, void (C::*memberFunction)())
{
theClass = aClass;
mf = memberFunction;
}
void CallTheThing()
{
if ( theClass )
(theClass->*mf)();
}
};
//Specialization for any function
template <>
struct TheCaller<void>
{
TheCaller() : mf(nullptr) {}
void (*mf)();
void SetTheThing(void (*memberFunction)())
{
mf = memberFunction;
}
void CallTheThing()
{
if ( mf )
mf();
}
};
struct Bar
{
void DoTheBarThing()
{ std::cout << "DoTheBarThing called" << std::endl; }
};
void AFunction()
{ std::cout << "AFunction called" << std::endl; }
int main()
{
TheCaller<Bar> foo;
Bar bar;
foo.SetTheThing(&bar, &Bar::DoTheBarThing);
foo.CallTheThing();
TheCaller<> foo2;
foo2.SetTheThing(&AFunction);
foo2.CallTheThing();
}