- Modern C++:Efficient and Scalable Application Development
- Richard Grimes Marius Bancila
- 491字
- 2021-06-10 18:28:16
Getting pointers to object members
If you need to get access to the address of a class data member through an instance (assuming the data member is public), you simply use the & operator:
struct point { double x; double y; };
point p { 10.0, 10.0 };
int *pp = &p.x;
In this case struct is used to declare point so that the members are public by default. The second line uses an initialization list to construct a point object with two values, and then the final line gets a pointer to one of the data members. Of course, the pointer cannot be used after the object has been destroyed. Data members are allocated in memory (in this case on the stack), so the address operator merely gets a pointer to that memory.
Function pointers are a different case. There will only be one copy of the method in memory, regardless of how many instances of the class are created, but because methods are called using the __thiscall calling convention (with a hidden this parameter) you have to have a function pointer that can be initialized with a pointer to an object to provide the this pointer. Consider this class:
class cartesian_vector
{
public:
// other items
double get_magnitude() const
{
return std::sqrt((this->x * this->x) + (this->y * this->y));
}
};
We can define a function pointer to the get_magnitude method like this:
double (cartesian_vector::*fn)() const = nullptr;
fn = &cartesian_vector::get_magnitude;
The first line declares a function pointer. This is similar to the C function pointer declarations except that there is an inclusion of the class name in the pointer type. This is needed so that the compiler knows that it has to provide a this pointer in any call through this pointer. The second line obtains a pointer to the method. Notice that no object is involved. You are not getting a function pointer to a method on an object; you are getting a pointer to a method on a class that must be called through an object. To call the method through this pointer, you need to use the pointer to the member operator .* on an object:
cartesian_vector vec(1.0, 1.0);
double mag = (vec.*fn)();
The first line creates an object and the second line calls the method. The pointer to the member operator says that the function pointer on the right is called with the object on the left. The address of the object on the left is used for the this pointer when the method is called. As this is a method, we need to provide a parameter list, which in this case is empty (if you have parameters, they would be in the pair of parentheses on the right of this statement). If you have an object pointer, then the syntax is similar, but you use the ->* pointer to the member operator:
cartesian_vector *pvec = new cartesian_vector(1.0, 1.0);
double mag = (pvec->*fn)();
delete pvec;