Deriving a pointer type to the non-pointer class member
In book named "Using C++" by Rob McGregor there is following example of using pointer-to-member operator
class mycls
{
public:
int member;
int *ptr;
};
void main()
{
mycls MyClass;
// Derive a pointer type to the non-pointer class member
int mycls::*member = &mycls::member;
MyClass.ptr = new int;
mycls* pMyClass = &MyClass;
pMyClass->*member = 5;
*MyClass.ptr = 10;
cout << "pMyClass->*member = " << pMyClass->*member开发者_高级运维 << "\n"; // pMyClass->*member = 5
cout << "MyClass.*member = " << MyClass.*member << "\n"; // MyClass.*member = 5
cout << "*MyClass.ptr = " << *MyClass.ptr << "\n"; // *MyClass.ptr = 10
cout << "*pMyClass->ptr = " << *pMyClass->ptr << "\n"; // *pMyClass->ptr = 10
delete MyClass.ptr;
}
In this example I don't understand why member variable mycls::member
becomes maybe a pointer after (guessing) this line of code:
int mycls::*member = &mycls::member;
What this does?
Suppose you had a local variable:
int member;
You could make a pointer to it with:
int *ptr = &member;
To get the pointer to member syntax, we just append mycls::
in the appropriate places:
int mycls::*member = &mycls::member;
It might be clearer with an example that shows how the pointer can switch between any members of the class that are of the correct type:
class C
{
public:
int a;
int b;
};
void main()
{
// make pointer to member, initially pointing to a
int C::*ptrToMember = &C::a;
C x;
C *ptrToObj = &x; // make pointer to object x
ptrToObj->*ptrToMember = 2; // store in a;
ptrToMember = &C::b; // change pointer to b
ptrToObj->*ptrToMember = 3; // store in b;
}
Note how we create the pointer to the member a
before we've created an object of type C
. It's only a pointer to a member, not a pointer to the member of a specific object. In the 'store' steps, we have to say which object as well as which member.
Update
In the comments the OP asked if this is the same:
int *ptr = &(ptrToObj->a);
No, it's not. That is a pointer to any int
, anywhere in memory.
The easiest way to understand this is to think of what it means technically. A "pointer" is an absolute location in memory: where to find an object. A "pointer-to-member" is a relative location, sometimes called an offset: where to find an object within the storage of an outer object. Internally they are just numbers. A pointer-to-member has to be added to an ordinary pointer to make another pointer.
So if you have a pointer to an object (an int
is an object!), you can use it to change what is stored at that absolute location in memory:
*ptr = 123;
But if you have a pointer-to-member, it is not a memory location. It is an offset, an amount to be added to a memory location. You cannot use it by itself. You must "add" it to an object pointer:
ptrToObj->*ptrToMember = 132;
This means: go to the location in memory ptrToObj
, then move along by the distance ptrToMember
.
He called the class member member
and the pointer-to-member member
, confusing the issue. Does renaming them like this help?
Class:
class SampleClass
{
public:
int m_data;
int* m_pointer;
};
Usage:
int main()
{
SampleClass sample;
// Derive a pointer type to the non-pointer class member
int SampleClass::*pointerToMember = &SampleClass::m_data;
sample.m_pointer = new int;
SampleClass* pSample = &sample;
pSample->*pointerToMember = 5;
*sample.m_pointer = 10;
// pSample->*pointerToMember = 5
cout << "pSample->*pointerToMember = "
<< pSample->*pointerToMember << "\n";
// sample.*pointerToMember = 5
cout << "sample.*pointerToMember = "
<< sample.*pointerToMember << "\n";
// *sample.m_pointer = 10
cout << "*sample.m_pointer = "
<< *sample.m_pointer << "\n";
// *pSample->m_pointer = 10
cout << "*pSample->m_pointer = "
<< *pSample->m_pointer << "\n";
delete sample.m_pointer;
}
[Code]
Edit: Re "I'm still currious whether int *ptr = &(ptrToObj->a);
is the same as using pointer to a member like in the book":
It's not a pointer-to-member. It is just a normal pointer to memory that happens to be in an object.
You can see the syntax in use here:
Class:
class C
{
public:
int a;
int b;
};
Usage:
int main()
{
// make pointer to member, initially pointing to a
int C::*ptrToMember = &C::a;
C x = {10, 11};
C *ptrToObj = &x; // make pointer to object x
cout << "a initial value: " << ptrToObj->*ptrToMember << endl;
ptrToObj->*ptrToMember = 2; // store in a;
cout << "a after change: " << ptrToObj->*ptrToMember << endl;
ptrToMember = &C::b; // change pointer to b
cout << "b initial value: " << ptrToObj->*ptrToMember << endl;
ptrToObj->*ptrToMember = 3; // store in b;
cout << "b after change: " << ptrToObj->*ptrToMember << endl;
int* ptr = &(ptrToObj->a);
cout << "ptr to a: " << *ptr << endl;
ptr = &(ptrToObj->b);
cout << "ptr to b: " << *ptr << endl;
}
[Code]
The asterisk character in the declaration is part of the type.
Your declaration breaks down into
Type: int mycls::*
Variable name: member
Initialiser: = &mycls::member
This new variable member
points is a member pointer to an int held in a mycls
. It doesn't have to point to a mycls::member
.
精彩评论