我有一个按钮类。我希望按钮类的构造函数能够在按下按钮时调用它将调用的函数。如果按钮类只从一个类中获取一个函数,这将很容易,但按钮的构造函数采用函数的目的是无论在哪个类中创建按钮都能够存储指针在它创建的类中的函数。
举例说明:
struct Button {
Button(void (*functionPtr)()) {
// Store the function pointer to be called later
}
};
struct SomeClass {
void LoadFile();
SomeClass() {
Button* temp1 = new Button(&LoadFile); // ???
}
};
struct AnotherClass {
void SaveFile();
SomeClass() {
Button* temp2 = new Button(&SaveFile); // ???
}
};
我该如何做到这一点?
答案 0 :(得分:3)
指向函数的指针和指向成员函数的指针,尽管看起来非常相似,但实际上是完全不同的野兽。
void (*functionPtr)()
是一个指向函数的指针,该函数不带参数并返回void。 &AnotherClass::SaveFile
是指向AnotherClass
的成员函数的指针...其类型为void (AnotherClass::*)()
。请注意,类名是类型的一部分,因此您不能简单地将指向成员的函数存储到任意类。此外,要调用指向成员的指针函数,您需要一个实例指针 - 您必须以某种方式存储它,但那些也会有不同的类型!
在C ++ 11中你可以做的是使用type-erasure:
std::function<void()> callback;
并为其指定一个任意的可调用对象:
template <typename F>
Button(F cb)
: callback(cb)
{ }
然后您可以使用std::bind
:
Button* temp1 = new Button(std::bind(&OtherClass::LoadFile, this));
Button* temp2 = new Button(std::bind(&AnotherClass::SaveFile, this));
现在temp1->callback()
实际上会在LoadFile()
的实例上调用它OtherClass
。这是你想要的。而且,我们仍然可以使用免费功能:
void whatever();
Button* temp3 = new Button(whatever);
插入有关使用原始指针和new
以及首选unique_ptr
的常见警告。
答案 1 :(得分:0)
你实际上没有一个指向成员函数的指针,因为它对于调用该对象的隐藏this
指针没有意义。
您尝试解决的问题有一些常见的解决方案。
C
方式:
除了函数指针之外还存储void*
。然后在回调中传递void*
int。这不太“安全”,但在C中很常见。
OOP方式#1:
子类Button
并在基类上有一个虚函数,比如可以在子类中实现的onPress
。
OOP方式#2:
有一个独立于自定义类实现的Button
的回调接口。
编辑:或者使用评论中提到的lambdas。我自己仍然以现代的方式重新学习C ++。