问题
The Problem
Lets say that we have a simple class to sort a list of integers,
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;
};
As you can see when were going to sort, we ask for a specific algorithm to use, and depending on it, we assign the function to a function pointer which at the end, we call it to search.
But the question is, why do we call the function pointer like this: (this->*(pfSort))();
and not like this: pfSort()
?
回答1:
How to use function pointers to access member functions?
There is no way to do that directly because function pointers can only point to functions ; not to (non-static) member functions.
Instead, you can use a member function pointer - which you did use in the example.
why do we call the function pointer like this: (this->*(pfSort))(); and not like this: pfSort()?
Because it is not a function pointer. It is a member function pointer. And the syntax of calling a (non-static) member function is so, because the instance argument must be passed - which in this case is *this
.
回答2:
Lets look at this simple example,
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!
}
By looking at the example, we can see that the only way to call the member function pointer is by providing the dereferenced function pointer as the function body (in this case SayHello
). And the object needs to be instantiated in order to do this, just like how we would do it if were going to call the SayHello()
method directly.
Why do we need to instantiate the object before calling it?
That's because in order for the function to access other member variables and member functions, the object needs to be instantiated. This wont be an issue for static functions (because they cant access member variables and member functions).
Why dereferenced function pointer?
Well that's because your not directly storing the function pointer. Your storing the address of the function pointer (g.pfHello = &Greeting::SayHello;
). This is why we need to dereference it.
That's why we have to use this: (this->*(pfSort))();
instead of this: pfSort()
.
Hope this would clear some doubts!
来源:https://stackoverflow.com/questions/65733375/how-to-use-function-pointers-to-access-member-functions