Pointer to class data member “::*”

后端 未结 15 1643
清歌不尽
清歌不尽 2020-11-21 11:47

I came across this strange code snippet which compiles fine:

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;
         


        
相关标签:
15条回答
  • 2020-11-21 12:23

    Suppose you have a structure. Inside of that structure are * some sort of name * two variables of the same type but with different meaning

    struct foo {
        std::string a;
        std::string b;
    };
    

    Okay, now let's say you have a bunch of foos in a container:

    // key: some sort of name, value: a foo instance
    std::map<std::string, foo> container;
    

    Okay, now suppose you load the data from separate sources, but the data is presented in the same fashion (eg, you need the same parsing method).

    You could do something like this:

    void readDataFromText(std::istream & input, std::map<std::string, foo> & container, std::string foo::*storage) {
        std::string line, name, value;
    
        // while lines are successfully retrieved
        while (std::getline(input, line)) {
            std::stringstream linestr(line);
            if ( line.empty() ) {
                continue;
            }
    
            // retrieve name and value
            linestr >> name >> value;
    
            // store value into correct storage, whichever one is correct
            container[name].*storage = value;
        }
    }
    
    std::map<std::string, foo> readValues() {
        std::map<std::string, foo> foos;
    
        std::ifstream a("input-a");
        readDataFromText(a, foos, &foo::a);
        std::ifstream b("input-b");
        readDataFromText(b, foos, &foo::b);
        return foos;
    }
    

    At this point, calling readValues() will return a container with a unison of "input-a" and "input-b"; all keys will be present, and foos with have either a or b or both.

    0 讨论(0)
  • 2020-11-21 12:24

    It's a "pointer to member" - the following code illustrates its use:

    #include <iostream>
    using namespace std;
    
    class Car
    {
        public:
        int speed;
    };
    
    int main()
    {
        int Car::*pSpeed = &Car::speed;
    
        Car c1;
        c1.speed = 1;       // direct access
        cout << "speed is " << c1.speed << endl;
        c1.*pSpeed = 2;     // access via pointer to member
        cout << "speed is " << c1.speed << endl;
        return 0;
    }
    

    As to why you would want to do that, well it gives you another level of indirection that can solve some tricky problems. But to be honest, I've never had to use them in my own code.

    Edit: I can't think off-hand of a convincing use for pointers to member data. Pointer to member functions can be used in pluggable architectures, but once again producing an example in a small space defeats me. The following is my best (untested) try - an Apply function that would do some pre &post processing before applying a user-selected member function to an object:

    void Apply( SomeClass * c, void (SomeClass::*func)() ) {
        // do hefty pre-call processing
        (c->*func)();  // call user specified function
        // do hefty post-call processing
    }
    

    The parentheses around c->*func are necessary because the ->* operator has lower precedence than the function call operator.

    0 讨论(0)
  • 2020-11-21 12:27

    IBM has some more documentation on how to use this. Briefly, you're using the pointer as an offset into the class. You can't use these pointers apart from the class they refer to, so:

      int Car::*pSpeed = &Car::speed;
      Car mycar;
      mycar.*pSpeed = 65;
    

    It seems a little obscure, but one possible application is if you're trying to write code for deserializing generic data into many different object types, and your code needs to handle object types that it knows absolutely nothing about (for example, your code is in a library, and the objects into which you deserialize were created by a user of your library). The member pointers give you a generic, semi-legible way of referring to the individual data member offsets, without having to resort to typeless void * tricks the way you might for C structs.

    0 讨论(0)
提交回复
热议问题