将成员函数作为参数传递给构造函数
Passing a member function as an argument to a constructor
我有一个按钮 class。我希望按钮 class 的构造函数采用按下按钮时将调用的函数。如果按钮 class 只是从一个 class 中获取函数,这将很容易,但是按钮的构造函数获取函数的目的是无论按钮是在什么 class 中创建的它将能够在创建它的 class 中存储指向函数的指针。
举例说明:
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); // ???
}
};
我怎样才能做到这一点?
您不能真正拥有指向成员函数的指针,因为它是无意义的 w/o 调用对象的隐藏 this
指针。
对于您要解决的问题,有一些常见的解决方案。
C
方式:
除了函数指针外,还存储了一个void*
。然后传递 void*
int 回调。这较少 "safe",但在 C 中很常见。
OOP 方式 #1:
Subclass Button
并且在基础 class 上有一个虚函数,比如 onPress
可以在 subclass 中实现。
OOP 方式 #2:
有一个独立于您的自定义 classes 实现的 Button
的回调接口。
编辑:或使用评论中提到的 lambda。我自己仍在以现代方式重新学习 C++。
指向函数的指针和指向成员函数的指针,尽管看起来非常相似,但实际上是完全不同的野兽。
void (*functionPtr)()
是指向不带参数且 returns 无效的函数的指针。 &AnotherClass::SaveFile
是指向 AnotherClass
的 成员 函数的指针...它的类型是 void (AnotherClass::*)()
。请注意 class 名称是类型的一部分,因此您不能简单地将指向成员函数的指针存储到任意 class。此外,要调用指向成员函数的指针,您需要一个实例指针——您必须以某种方式存储它,但它们也有不同的类型!
在 C++11 中你可以做的是使用类型擦除:
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()
实际上会在 OtherClass
的实例上调用 LoadFile()
,它是用它构造的。这就是你想要的。而且,我们仍然可以使用免费功能:
void whatever();
Button* temp3 = new Button(whatever);
插入有关使用原始指针和 new
并首选 unique_ptr
的常见注意事项。
我有一个按钮 class。我希望按钮 class 的构造函数采用按下按钮时将调用的函数。如果按钮 class 只是从一个 class 中获取函数,这将很容易,但是按钮的构造函数获取函数的目的是无论按钮是在什么 class 中创建的它将能够在创建它的 class 中存储指向函数的指针。
举例说明:
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); // ???
}
};
我怎样才能做到这一点?
您不能真正拥有指向成员函数的指针,因为它是无意义的 w/o 调用对象的隐藏 this
指针。
对于您要解决的问题,有一些常见的解决方案。
C
方式:
除了函数指针外,还存储了一个void*
。然后传递 void*
int 回调。这较少 "safe",但在 C 中很常见。
OOP 方式 #1:
Subclass Button
并且在基础 class 上有一个虚函数,比如 onPress
可以在 subclass 中实现。
OOP 方式 #2:
有一个独立于您的自定义 classes 实现的 Button
的回调接口。
编辑:或使用评论中提到的 lambda。我自己仍在以现代方式重新学习 C++。
指向函数的指针和指向成员函数的指针,尽管看起来非常相似,但实际上是完全不同的野兽。
void (*functionPtr)()
是指向不带参数且 returns 无效的函数的指针。 &AnotherClass::SaveFile
是指向 AnotherClass
的 成员 函数的指针...它的类型是 void (AnotherClass::*)()
。请注意 class 名称是类型的一部分,因此您不能简单地将指向成员函数的指针存储到任意 class。此外,要调用指向成员函数的指针,您需要一个实例指针——您必须以某种方式存储它,但它们也有不同的类型!
在 C++11 中你可以做的是使用类型擦除:
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()
实际上会在 OtherClass
的实例上调用 LoadFile()
,它是用它构造的。这就是你想要的。而且,我们仍然可以使用免费功能:
void whatever();
Button* temp3 = new Button(whatever);
插入有关使用原始指针和 new
并首选 unique_ptr
的常见注意事项。