如何使用函数指针访问成员函数?

How to use function pointers to access member functions?

问题
假设我们有一个简单的 class 来对整数列表进行排序,

class Sorter {
public:
    Sorter() {}
    ~Sorter() {}

    enum class Algorithm { Bubble, Heap, Merge, Insertion };

    void SetVector(const std::vector<int>& vec) { mVector = vec; }

    void Sort(Algorithm algo)
    {
        void (Sorter:: * pfSort)() = nullptr;

        switch (algo)
        {
        case Sorter::Algorithm::Bubble:
            pfSort = &Sorter::BubbleSort;
            break;
        case Sorter::Algorithm::Heap:
            pfSort = &Sorter::HeapSort;
            break;
        case Sorter::Algorithm::Merge:
            pfSort = &Sorter::MergeSort;
            break;
        case Sorter::Algorithm::Insertion:
            pfSort = &Sorter::InsertionSort;
            break;
        default:
            std::cerr << "Invalid or Unsupported Sort Algorithm!";
            break;
        }

        (this->*(pfSort))();
    }

private:
    void BubbleSort() { ... }
    void HeapSort() { ... }
    void MergeSort() { ... }
    void InsertionSort() { ... }

private:
    std::vector<int> mVector;
};

正如你所见,我们什么时候要排序,我们要求使用特定的算法,并根据它,我们将函数分配给一个函数指针,最后我们调用它来搜索。

但问题是,为什么我们这样调用函数指针:(this->*(pfSort))();而不是这样:pfSort()?

让我们看看这个简单的例子,

struct Greeting {
    void SayHello() { std::cout << "Hello!\n"; }

    void (Greeting::*pfHello)() = nullptr;
};

int main()
{
    Greeting g;

    // Lets assign the function pointer to the pfHello variable.
    g.pfHello = &Greeting::SayHello;

    // Now lets call it like a traditional function pointer.
    g.pfHello();    // Triggers an error!

    // Now lets call it by dereferencing it.
    (*g.pfHello)(); // Still triggers an error..

    // Okay lets call it just like g.SayHello() but by swapping the dereferenced pointer with SayHello.
    (g.*(g.pfHello))(); // Works fine!
}

通过查看示例,我们可以看到调用成员函数指针的唯一方法是提供取消引用的函数指针作为函数体(在本例中SayHello).并且需要实例化对象才能执行此操作,就像我们直接调用 SayHello() 方法一样。

为什么我们需要在调用之前实例化对象?
那是因为为了让函数访问其他成员变量和成员函数,对象需要被实例化。这不会成为静态函数的问题(因为它们无法访问成员变量和成员函数)。

为什么 取消引用函数指针
那是因为你没有直接存储函数指针。您存储函数指针的地址 (g.pfHello = &Greeting::SayHello;)。这就是我们需要取消引用它的原因。

这就是为什么我们必须使用这个:(this->*(pfSort))(); 而不是这个:pfSort().

希望这会消除一些疑问!

How to use function pointers to access member functions?

没有办法直接这样做,因为函数指针只能指向函数;不是(非静态)成员函数。

相反,您可以使用成员函数指针 - 您在示例中确实使用了它。

why do we call the function pointer like this: (this->*(pfSort))(); and not like this: pfSort()?

因为它不是函数指针。它是一个成员函数指针。调用(非静态)成员函数的语法是这样的,因为必须传递实例参数——在这种情况下是 *this.