将成员函数作为参数传递给构造函数

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 的常见注意事项。