理解获取非静态成员地址以形成指向成员函数的指针的错误?
Understanding error with taking address of non-static member to form pointer to member function?
我有一个问题,我不确定如何解决。
我正在使用一个库,其 class 的实例是通过传递对一些函数的引用来构造的。
void func_on_enter() {...}
void func() {...}
void func_on_exit(){...}
State state_a(&func_on_enter, &func, &func_on_exit);
我正在写一个 class,其中包含此 class 的一个实例,因此我尝试过这样的事情:
class MyClass{
private:
void func_on_enter() {...}
void func() {...}
void func_on_exit(){...}
State _state_a;
public:
MyClass() : _state_a(&func_on_enter, &func, &func_on_exit) {}
};
我收到错误 "ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&MyClass::_func_on_enter'"(显然其他两种方法也一样)。编译器很有帮助地提供了一个解决方案,我试过了。
但是编译器随后提醒我没有匹配函数来调用 'State::State(void (MyClass::*)(), void (MyClass::*)(), (MyClass::*)())'
并且它没有已知的从 'void (MyClass::*)()'
到 'void(*)()'
的转换。
我尝试阅读有关此错误的类似问题,但似乎找不到我既理解又能在这种情况下提供帮助的解决方案。
我考虑过尝试向 State 添加一个重载构造函数,但是考虑到我可以从任何其他 [=36] 调用它,在 class by class 情况下这样做似乎很荒谬=].
我也想了一会儿,我可以将函数设为静态(因为它们对于 MyClass 的所有实例都是相同的),但我很快记起它们将无法使用非静态成员变量MyClass 的。
有没有一种方法可以提供转换或以另一种方式为 State 构造函数提供指针?
在这方面我真的需要一些帮助,因为我对如何前进的想法很困惑。任何帮助或提示将不胜感激!
void func_on_enter() {...}
void func() {...}
void func_on_exit(){...}
State state_a(&func_on_enter, &func, &func_on_exit);
为此,State
的构造函数必须接受类型为 void(*)()
的函数指针。
_state_a(&MyClass::func_on_enter, &MyClass::func, &MyClass::func_on_exit)
为此,State
的构造函数必须接受 void (MyClass::*)()
类型的成员函数指针。成员函数指针不可转换为函数指针。
您可以更改 State
的构造函数以接受正确类型的指针。
指向非静态成员函数的指针无法转换为普通函数指针。 void (MyClass::*)()
需要一个 MyClass
对象来操作。原始指针不能保存任何类型的状态,因此 void(*)()
无法存储有关要操作哪个 MyClass
对象的信息。
幸运的是,标准库有一个 class 专为此目的设计的模板:std::function
。 std::function
或多或少是原始函数指针的替代品,但它可以容纳与给定签名兼容的任何类型的可调用对象。这意味着它可以保持回调到 class:
的特定实例所需的状态
class State {
private:
std::function<void()> on_enter;
std::function<void()> func;
std::function<void()> on_exit;
public:
State(std::function<void()> on_enter, std::function<void()> func, std::function<void()> on_exit)
: on_enter{std::move(on_enter)},
func{std::move(func)},
on_exit{std::move(on_exit)}
{}
void do_something() {
on_enter();
// stuff
func();
// more stuff
on_exit();
}
};
class MyClass {
private:
void func_on_enter() {}
void func() {}
void func_on_exit(){}
State state_a;
public:
MyClass()
: state_a([this]() { func_on_enter(); },
[this]() { func(); },
[this]() { func_on_exit(); })
{}
};
在这里,我没有将指针直接传递给您的成员函数,而是将它们包装在捕获要回调的对象的 this
指针的 lambda 中。现在 State
对象可以调用这些成员,并且他们知道要对 MyClass
的哪个实例进行操作。
不过要注意对象的生命周期。由于 state_a
保留指向其 MyClass
实例的指针,因此您需要确保 MyClass
的 copy/move 构造函数和赋值运算符做正确的事情。编译器提供的默认实现是不够的。
我有一个问题,我不确定如何解决。
我正在使用一个库,其 class 的实例是通过传递对一些函数的引用来构造的。
void func_on_enter() {...}
void func() {...}
void func_on_exit(){...}
State state_a(&func_on_enter, &func, &func_on_exit);
我正在写一个 class,其中包含此 class 的一个实例,因此我尝试过这样的事情:
class MyClass{
private:
void func_on_enter() {...}
void func() {...}
void func_on_exit(){...}
State _state_a;
public:
MyClass() : _state_a(&func_on_enter, &func, &func_on_exit) {}
};
我收到错误 "ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&MyClass::_func_on_enter'"(显然其他两种方法也一样)。编译器很有帮助地提供了一个解决方案,我试过了。
但是编译器随后提醒我没有匹配函数来调用 'State::State(void (MyClass::*)(), void (MyClass::*)(), (MyClass::*)())'
并且它没有已知的从 'void (MyClass::*)()'
到 'void(*)()'
的转换。
我尝试阅读有关此错误的类似问题,但似乎找不到我既理解又能在这种情况下提供帮助的解决方案。
我考虑过尝试向 State 添加一个重载构造函数,但是考虑到我可以从任何其他 [=36] 调用它,在 class by class 情况下这样做似乎很荒谬=].
我也想了一会儿,我可以将函数设为静态(因为它们对于 MyClass 的所有实例都是相同的),但我很快记起它们将无法使用非静态成员变量MyClass 的。
有没有一种方法可以提供转换或以另一种方式为 State 构造函数提供指针?
在这方面我真的需要一些帮助,因为我对如何前进的想法很困惑。任何帮助或提示将不胜感激!
void func_on_enter() {...} void func() {...} void func_on_exit(){...} State state_a(&func_on_enter, &func, &func_on_exit);
为此,State
的构造函数必须接受类型为 void(*)()
的函数指针。
_state_a(&MyClass::func_on_enter, &MyClass::func, &MyClass::func_on_exit)
为此,State
的构造函数必须接受 void (MyClass::*)()
类型的成员函数指针。成员函数指针不可转换为函数指针。
您可以更改 State
的构造函数以接受正确类型的指针。
指向非静态成员函数的指针无法转换为普通函数指针。 void (MyClass::*)()
需要一个 MyClass
对象来操作。原始指针不能保存任何类型的状态,因此 void(*)()
无法存储有关要操作哪个 MyClass
对象的信息。
幸运的是,标准库有一个 class 专为此目的设计的模板:std::function
。 std::function
或多或少是原始函数指针的替代品,但它可以容纳与给定签名兼容的任何类型的可调用对象。这意味着它可以保持回调到 class:
class State {
private:
std::function<void()> on_enter;
std::function<void()> func;
std::function<void()> on_exit;
public:
State(std::function<void()> on_enter, std::function<void()> func, std::function<void()> on_exit)
: on_enter{std::move(on_enter)},
func{std::move(func)},
on_exit{std::move(on_exit)}
{}
void do_something() {
on_enter();
// stuff
func();
// more stuff
on_exit();
}
};
class MyClass {
private:
void func_on_enter() {}
void func() {}
void func_on_exit(){}
State state_a;
public:
MyClass()
: state_a([this]() { func_on_enter(); },
[this]() { func(); },
[this]() { func_on_exit(); })
{}
};
在这里,我没有将指针直接传递给您的成员函数,而是将它们包装在捕获要回调的对象的 this
指针的 lambda 中。现在 State
对象可以调用这些成员,并且他们知道要对 MyClass
的哪个实例进行操作。
不过要注意对象的生命周期。由于 state_a
保留指向其 MyClass
实例的指针,因此您需要确保 MyClass
的 copy/move 构造函数和赋值运算符做正确的事情。编译器提供的默认实现是不够的。