在不知道哪个的情况下调用C++成员函数指针class
Call C++ member function pointer without knowing which class
我正在尝试调用成员函数,可能给定对象指针,但不知道 class 成员函数来自什么。这可能吗?
基本上我想要像下面这样的东西工作。
class Foo{
public:
Foo(void* object): obj(object) {}
void callFunc(void (*func)()){
obj->*func();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
callFunc(someFunc);
}
void someFunc(){
cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
它看起来很像 XY 问题。无论如何,让我们尝试按原样回复您的问题。
一个函数成员被绑定到它所属的 class 的类型,除非它是一个静态的(后者就像一个普通的函数指针一样对待,你甚至不必传递指向要调用它的实例的指针)。
因此,您可以将 callFunc
设为函数模板并让它为您推断类型:
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
在 wandbox 上查看并 运行。
请注意,如果 static_cast
您的 obj
的原始类型(您擦除后放入 void *
的类型)不是 T
.
这是您可以在上方 link 处看到的完整代码:
#include<iostream>
class Foo{
public:
Foo(void* object): obj(object) {}
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
foo.callFunc(&Bar::someFunc);
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
这是一个 XY 问题。使用 std::function
and/or lambda。
#include <functional>
#include <iostream>
class Foo{
public:
template<class F>
void callFunc(F&& f){
f();
}
};
class Bar : public Foo{
public:
Bar(): foo() {}
void callSomeFunc(){
this->callFunc([this]{ someFunc(); });
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
虽然我发现@skypjack 提供的解决方案更优雅,但这里的解决方案将 Foo
-class(而不是 "only" 函数)作为一个整体进行模板化。因此 obj
的类型在整个 Foo
-class 中都是已知的,这可能是一个优势(也可能不是)。
此外,另请参阅将成员与关联对象一起存储的解决方案。也许它在某些方面有帮助:
#include <functional>
#include <iostream>
template<class T>
class Foo {
public:
Foo(T& obj) : _obj(obj) {}
void callFuncOnObj(void (T::*func)(void)) {
auto fn = mem_fn(func);
fn(_obj);
}
private:
T &_obj;
};
class Bar{
public:
Bar() : d(*this) {}
void callSomeFunc(){
d.callFuncOnObj(&Bar::someFunc);
}
void someFunc(){
cout << "hi Bar1\n";
}
private:
Foo<Bar> d;
};
class Foo2 {
public:
Foo2(std::function<void(void)> f) : _f(f) {}
void callFunction() {
_f();
}
private:
std::function<void(void)> _f;
};
class Bar2{
public:
Bar2() : d(std::bind(&Bar2::someFunc,this)) {}
void callSomeFunc(){
d.callFunction();
}
void someFunc(){
cout << "hi Bar2\n";
}
private:
Foo2 d;
};
int main(){
Bar bar;
bar.callSomeFunc();
Bar2 bar2;
bar2.callSomeFunc();
return 0;
}
我正在尝试调用成员函数,可能给定对象指针,但不知道 class 成员函数来自什么。这可能吗?
基本上我想要像下面这样的东西工作。
class Foo{
public:
Foo(void* object): obj(object) {}
void callFunc(void (*func)()){
obj->*func();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
callFunc(someFunc);
}
void someFunc(){
cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
它看起来很像 XY 问题。无论如何,让我们尝试按原样回复您的问题。
一个函数成员被绑定到它所属的 class 的类型,除非它是一个静态的(后者就像一个普通的函数指针一样对待,你甚至不必传递指向要调用它的实例的指针)。
因此,您可以将 callFunc
设为函数模板并让它为您推断类型:
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
在 wandbox 上查看并 运行。
请注意,如果 static_cast
您的 obj
的原始类型(您擦除后放入 void *
的类型)不是 T
.
这是您可以在上方 link 处看到的完整代码:
#include<iostream>
class Foo{
public:
Foo(void* object): obj(object) {}
template<typename T>
void callFunc(void (T::*func)()){
(static_cast<T*>(obj)->*func)();
}
private:
void* obj;
};
class Bar{
public:
Bar(): foo(this) {}
void callSomeFunc(){
foo.callFunc(&Bar::someFunc);
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
这是一个 XY 问题。使用 std::function
and/or lambda。
#include <functional>
#include <iostream>
class Foo{
public:
template<class F>
void callFunc(F&& f){
f();
}
};
class Bar : public Foo{
public:
Bar(): foo() {}
void callSomeFunc(){
this->callFunc([this]{ someFunc(); });
}
void someFunc(){
std::cout << "hi\n";
}
private:
Foo foo;
};
int main(){
Bar bar;
bar.callSomeFunc();
return 0;
}
虽然我发现@skypjack 提供的解决方案更优雅,但这里的解决方案将 Foo
-class(而不是 "only" 函数)作为一个整体进行模板化。因此 obj
的类型在整个 Foo
-class 中都是已知的,这可能是一个优势(也可能不是)。
此外,另请参阅将成员与关联对象一起存储的解决方案。也许它在某些方面有帮助:
#include <functional>
#include <iostream>
template<class T>
class Foo {
public:
Foo(T& obj) : _obj(obj) {}
void callFuncOnObj(void (T::*func)(void)) {
auto fn = mem_fn(func);
fn(_obj);
}
private:
T &_obj;
};
class Bar{
public:
Bar() : d(*this) {}
void callSomeFunc(){
d.callFuncOnObj(&Bar::someFunc);
}
void someFunc(){
cout << "hi Bar1\n";
}
private:
Foo<Bar> d;
};
class Foo2 {
public:
Foo2(std::function<void(void)> f) : _f(f) {}
void callFunction() {
_f();
}
private:
std::function<void(void)> _f;
};
class Bar2{
public:
Bar2() : d(std::bind(&Bar2::someFunc,this)) {}
void callSomeFunc(){
d.callFunction();
}
void someFunc(){
cout << "hi Bar2\n";
}
private:
Foo2 d;
};
int main(){
Bar bar;
bar.callSomeFunc();
Bar2 bar2;
bar2.callSomeFunc();
return 0;
}