开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜