C++: Pointer to composite class data member

2019-06-14 02:52发布

问题:

Is it possible to access a composite class data member with pointers to members ? The following code is not valid but demonstrate the need.

For example:

class A
{
public:
    float fA;
};

class B
{
public:
    float fB;
    A a;
};

void test()
{
    // Use of member pointer to access B::fB member
    float B::*ptr = &B::fB; // -> OK
    B myB;
    myB.*ptr = 25.;

    // Use of member pointer to access B::a.fA member ???
    float B::*ptr2 = &B::a.fA; // -> ERROR
    B myB.*ptr2 = 25.;
}

I've complete my question here : Pointer to composite class data member - Part 2

回答1:

The obvious "reason" here is because fA is not a member of B. In this particular case, implementing it would probably not cause any particular problems, both orthogonality rules, and for member functions, I don't think it could be implemented.

What you can do, of course, is take the address of the A member of B, then get to fA through it:

A B::*ptr = &B::a;
(myB.*ptr).fa = 25.;

, for example. (I'm not sure that the parentheses are needed. It's not a constrution that I use often enough to have the precedences in my head.)



回答2:

I agree with commenters, that probably you should ask how to do what you want, not how to do what you think will do what you want :)

As for the question: no, you cannot access B::a.fA in this way. However, you can do the following:

A myA;
float A::*ptr2 = &A::fA; // -> OK now
myB.a.*ptr2 = 25.;

Or the following:

A B::*ptr3 = &B::a; 
(myB.*ptr3).fA = 1.0f;  // -> OK too


回答3:

That is some weird looking syntax but if I understand you correctly, you are trying to access fA through class B. If that is the case, then you will need to create an instance of class B before class A is available to be accessed. Basically, if B doesn't exist, you can't access what is inside of it. The error is just what it sounds like, "left of .fA must have a class/struct/union" meaning your compiler can't figure out what is to the left of fA so the "a" is undefined or doesn't exist. Also, you have a redefinition error in there with B myB :)



回答4:

No you cannot because the C++ syntax does not allow it. I don't see anything really special about what you're trying to do, but it's simply not considered in the language.

Note however that a pointer to data member is an object that given an instance will return a reference to a specific data member. You can implement this functionality manually relaxing the limitations:

struct A
{
    double x;
    double y;
    static double& x_of(void *p) { return ((A *)p)->x; }
    static double& y_of(void *p) { return ((A *)p)->y; }
};

struct B
{
    double z;
    A a;
    static double& x_of(void *p) { return ((B *)p)->a.x; }
    static double& y_of(void *p) { return ((B *)p)->a.y; }
    static double& z_of(void *p) { return ((B *)p)->z; }
};

The type of the pointer is just double& (*)(void *) and you can use this kind of trick even for example to return as member an element of an array.