views:

4149

answers:

9

I came across this strange code snippet which compiles fine:

class Car
{
    public:
    int speed;
};

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

Why does C++ have this pointer to a non-static data member of a class? What is the use of this strange pointer in real code?

+10  A: 

You can later access this member, on any instance:

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

  int mySpeed = myCar.*pSpeed;
  int yourSpeed = yourCar.*pSpeed;

  assert(mySpeed > yourSpeed); // ;-)

  return 0;
}

Note that you do need an instance to call it on, so it does not work like a delegate.
It is used rarely, I've needed it maybe once or twice in all my years.

Normally using an interface (i.e. a pure base class in C++) is the better design choice.

peterchen
But surely this is just bad practice? should do something like youcar.setspeed(mycar.getpspeed)
thecoshman
@thecoshman: entirely depends - hiding data members behind set/get methods is not encapsulation and merely a milkmaids attempt at interface abstraction. In many scenarios, "denormalization" to public members is a reasonable choice. But that discussion probably exceeds the confines of the comment functionality.
peterchen
+5  A: 

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 this 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.

AHelps
Could you share a code snippet example where this construct is useful? Thanks.
Ashwin
+1 for finding a reasonable use case
dmckee
I'm currently doing alot of this due to doing some DCOM work and using managed resource classes which involves doing a bit of work before each call, and using data members for internal representation to send off to com, plus templating,makes a lot of boiler plate code *much* smaller
Dan
+7  A: 

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 use them in my own code.

Edit: I can't think off-hand of a convincing use for pointer 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-seleceted member function to an object:

void Apply( SomeClass * c, SomeClass::*func() ) {
    // do hefty pre-call processing
    c->*func();  // call user specified function
    // do hefty post-call processing
}
anon
Could you show an example of a tricky situation where this is useful? Thanks.
Ashwin
A: 

I think you'd only want to do this if the member data was pretty large (e.g., an object of another pretty hefty class), and you have some external routine which only works on references to objects of that class. You don't want to copy the member object, so this lets you pass it around.

Andrew Jaffe
A: 

One way I've used it is if I have two implementations of how to do something in a class and I want to choose one at run-time without having to continually go through an if statement i.e.

class Algorithm
{
public:
    Algorithm() : m_impFn( &Algorithm::implementationA ) {}
    void frequentlyCalled()
    {
        // Avoid if ( using A ) else if ( using B ) type of thing
        (this->*m_impFn)();
    }
private:
    void implementationA() { /*...*/ }
    void implementationB() { /*...*/ }

    typedef void ( Algorithm::*IMP_FN ) ();
    IMP_FN m_impFn;
};

Obviously this is only practically useful if you feel the code is being hammered enough that the if statement is slowing things done eg. deep in the guts of some intensive algorithm somewhere. I still think it's more elegant than the if statement even in situations where it has no practical use but that's just my opnion.

Troubadour
+5  A: 

It makes it possible to bind member variables and functions in the uniform manner. The following is example with your Car class. More common usage would be binding std::pair::first and ::second when using in STL algorithms and Boost on a map.

#include <list>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>


class Car {
public:
    Car(int s): speed(s) {}
    void drive() {
        std::cout << "Driving at " << speed << " km/h" << std::endl;
    }
    int speed;
};

int main() {

    using namespace std;
    using namespace boost::lambda;

    list<Car> l;
    l.push_back(Car(10));
    l.push_back(Car(140));
    l.push_back(Car(130));
    l.push_back(Car(60));

    // Speeding cars
    list<Car> s;

    // Binding a value to a member variable.
    // Find all cars with speed over 60 km/h.
    remove_copy_if(l.begin(), l.end(),
                   back_inserter(s),
                   bind(&Car::speed, _1) <= 60);

    // Binding a value to a member function.
    // Call a function on each car.
    for_each(s.begin(), s.end(), bind(&Car::drive, _1));

    return 0;
}
Alex B
+7  A: 

Another application are intrusive lists. The element type can tell the list what its next/prev pointers are. So the list does not use hard-coded names but can still use existing pointers:

// say this is some existing structure. And we want to use
// a list. We can tell it that the next pointer
// is apple::next.
struct apple {
    int data;
    apple * next;
};

// simple example of a minimal intrusive list. Could specify the
// member pointer as template argument too, if we wanted:
// template<typename E, E *E::*next_ptr>
template<typename E>
struct List {
    List(E *E::*next_ptr):head(0), next_ptr(next_ptr) { }

    void add(E &e) {
        // access its next pointer by the member pointer
        e.*next_ptr = head;
        head = &e;
    }

    E * head;
    E *E::*next_ptr;
};

int main() {
    List<apple> lst(&apple::next);

    apple a;
    lst.add(a);
}
Johannes Schaub - litb
+2  A: 

You can use an array of pointer to (homogeneous) member data to enable a dual, named-member (i.e. x.data) and array-subscript (i.e. x[idx]) interface.

#include <cassert>
#include <cstddef>

struct vector3 {
    float x;
    float y;
    float z;

    float& operator[](std::size_t idx) {
     static float vector3::*component[3] = {
      &vector3::x, &vector3::y, &vector3::z
     };
     return this->*component[idx];
    }
};

int main()
{
    vector3 v = { 0.0f, 1.0f, 2.0f };

    assert(&v[0] == &v.x);
    assert(&v[1] == &v.y);
    assert(&v[2] == &v.z);

    for (std::size_t i = 0; i < 3; ++i) {
     v[i] += 1.0f;
    }

    assert(v.x == 1.0f);
    assert(v.y == 2.0f);
    assert(v.z == 3.0f);

    return 0;
}
Functastic