将成员函数作为参数传递给构造函数 [英] Passing a member function as an argument to a constructor
问题描述
我有一个按钮类。我想让按钮类的构造函数接受当按下按钮时它将调用的函数。这很容易,如果按钮类只是从一个类中取一个函数,但按钮的构造函数接受一个函数的目的是,无论什么类的按钮被创建,它将能够存储一个指针的函数
I have a button class. I want the button class's constructor to take the function it will call when the button is pressed. This would be easy if the button class was only taking a function from one class, but the purpose of the button's constructor taking a function is that no matter what class the button is created in it will be able to store a pointer to a function in the class it's created in.
示例:
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); // ???
}
};
如何使这项工作?
推荐答案
尽管看起来很相似,指针函数和指针成员函数实际上是完全不同的野兽。
A pointer-to-function and a pointer-to-member-function, despite seeming pretty similar, are actually entirely different beasts.
void(* functionPtr)()
是一个指向不带参数并返回void的函数的指针。 & AnotherClass :: SaveFile
是指向 AnotherClass
的成员函数的指针。它的类型是 void(AnotherClass :: *)()
。请注意,类名是类型的一部分,因此您不能简单地将指针到成员函数存储到任意类。此外,要调用指针到成员函数,你需要一个实例指针 - 你必须以某种方式存储,但那些也将有不同的类型!
void (*functionPtr)()
is a pointer to a function that takes no arguments and returns void. &AnotherClass::SaveFile
is a pointer to a member function of AnotherClass
... its type is void (AnotherClass::*)()
. Notice that the class name is part of the type, so you can't simply store a pointer-to-member-function to an arbitrary class. Furthermore, to call a pointer-to-member-function, you need an instance pointer - you'd have to store that somehow, but those would have different types too!
在C ++ 11中可以做的是使用type-erasure:
What you could do instead in C++11 is use type-erasure:
std::function<void()> callback;
并为其指定一个任意的可调用:
And assign an arbitrary callable to it:
template <typename F>
Button(F cb)
: callback(cb)
{ }
然后,您可以使用 std :: bind
创建按钮:
And then you could create a button using std::bind
:
Button* temp1 = new Button(std::bind(&OtherClass::LoadFile, this));
Button* temp2 = new Button(std::bind(&AnotherClass::SaveFile, this));
现在 temp1-> callback()
实际上会调用 OtherClass
的实例调用 LoadFile()
。这是你想要的。而且,我们仍然可以使用自由函数:
Now temp1->callback()
will actually call LoadFile()
on the instance of OtherClass
that it was constructed with. Which is what you wanted. And, we can still use free functions:
void whatever();
Button* temp3 = new Button(whatever);
插入关于使用原始指针和 new
并偏好 unique_ptr
。
Insert the usual caveats about using raw pointers and new
and preferring unique_ptr
.
这篇关于将成员函数作为参数传递给构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!