Pointers to member functions

So far, we have seen how we can use the Command pattern with function pointers and allow the client to call our functions without caring about the parameter types or counts. This is incredibly useful. But what about using commands with C++ objects? While we can get commands to work with objects, we need to think about the problem a little first.

The most basic way to call member functions is to simply hardcode them in the Execute method. For example, we could pass in an object to a command constructor and always call a very specific function. In the example, m_gameObject is a pointer to an object that was passed to the constructor. However, Draw is the hardcoded method that we always call. This is the same as hardcoding the function in Square5Command:

//Example of hard-coding a class method 
virtual void Execute(void)
{
m_gameObject->Draw();
}

Since m_gameObject is a variable, the object that will call Draw can change, but we are still always calling Draw. In this case, we don't have the option to call something else. This is still useful, but we would like the ability to call any method on a class type. So, how do we get this ability? We need to learn about pointers to member functions.

Using pointers to member functions isn't that different from pointers to non-member functions. However, the syntax is a little stranger than you might expect. Recall that when calling a non-static class method, the first parameter is always implicit to the pointer:

class SomeClass 
{
public:
//Example of what the compiler adds to every
//Non-static class method. THIS IS NOT REAL CODE
void SomeFunc(SomeClass* const this);
private:
int m_x;
};

The this pointer is what allows the class method to know which instance of the class it needs to modify. The compiler automatically passes it in as the first parameter to all non-static member functions, and the address of the this pointer is used as an offset for all member variables:

SomeClass someClass; 
//when we type this
someClass.SomeFunc();

//The compiler does something like this
SomeClass::SomeFunc(&someClass);

Even though it is implicitly passed in and is not part of the parameter list, we still have access to the this pointer in our code:

void SomeClass::SomeFunc(/* SomeClass* const this */) 
{
//We can still use the this pointer even though it isn't
//in the parameter list
this->m_x += 2;

//But we don't have to use it.
m_x += 2;
}

It is important to understand this because normal functions and member functions are not the same. Class members are part of the class scope and they have an implicit parameter. So, we can't save pointers to them like normal functions. The signature of a class method includes the class type, meaning we must use the scope resolution operator:

SomeClass someClass; 
//This doesn't work because they are not the same type
void (*BadFunc)(void) = &SomeClass::SomeFunc;

//We must include the class type
void (SomeClass::*GoodFunc)(void) = &SomeClass::SomeFunc;

Just having the correct pointer type is not enough. The class member access operators, known as the dot operator (.) and arrow operator ( -> ), are not designed to work with arbitrary function pointers. They are designed to work with known data types or known function names as declared in the class. Since our function pointer isn't known until runtime, these operators won't work. We need different operators that will know how to work with member function pointers. These operators are the pointer to member operators, ( .* ) and ( ->*).

Unfortunately, these operators have lower precedence than the function call operator. So, we need to add an extra set of parentheses around our object and our member function pointer:

SomeClass someClass; 
void (SomeClass::*GoodFunc)(void) = &SomeClass::SomeFunc;

//this doesn't work. GoodFunc isn't part of the class
someClass.GoodFunc();
//Extra parenthesis is required for .* and ->*
(someClass.*GoodFunc)();
There is a lot more to pointers to members. This section here was just a short introduction. If you want more information, please go to https://isocpp.org/wiki/faq/pointers-to-members.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.247.11