Указатель на элемент данных класса ":: *" - PullRequest
212 голосов
/ 22 марта 2009

Я наткнулся на этот странный фрагмент кода, который прекрасно компилируется:

class Car
{
    public:
    int speed;
};

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

Почему имеет C ++ этот указатель на нестатический член данных класса? Что использует этот странный указатель в реальном коде?

Ответы [ 14 ]

0 голосов
/ 25 декабря 2016

Просто добавьте несколько вариантов использования для ответа @ anon's & @ Oktalist, вот отличный материал для чтения о функциях указатель на член и указатель на элемент член. http://www.cs.wustl.edu/~schmidt/PDF/C++-ptmf4.pdf

0 голосов
/ 12 апреля 2016

Предположим, у вас есть структура. Внутри этой структуры * какое-то имя * две переменные одного типа, но с разным значением

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

Хорошо, теперь давайте представим, что у вас есть куча foo с в контейнере:

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

Хорошо, теперь предположим, что вы загружаете данные из отдельных источников, но данные представлены таким же образом (например, вам нужен тот же метод анализа).

Вы можете сделать что-то вроде этого:

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;
}

В этот момент вызов readValues() вернет контейнер с унисоном «input-a» и «input-b»; все ключи будут присутствовать, и у foos есть либо a, либо b, либо оба.

0 голосов
/ 18 ноября 2015

Вот пример, где может быть полезен указатель на элементы данных:

#include <iostream>
#include <list>
#include <string>

template <typename Container, typename T, typename DataPtr>
typename Container::value_type searchByDataMember (const Container& container, const T& t, DataPtr ptr) {
    for (const typename Container::value_type& x : container) {
        if (x->*ptr == t)
            return x;
    }
    return typename Container::value_type{};
}

struct Object {
    int ID, value;
    std::string name;
    Object (int i, int v, const std::string& n) : ID(i), value(v), name(n) {}
};

std::list<Object*> objects { new Object(5,6,"Sam"), new Object(11,7,"Mark"), new Object(9,12,"Rob"),
    new Object(2,11,"Tom"), new Object(15,16,"John") };

int main() {
    const Object* object = searchByDataMember (objects, 11, &Object::value);
    std::cout << object->name << '\n';  // Tom
}
0 голосов
/ 22 марта 2009

Я думаю, вы захотите сделать это, только если данные члена были довольно большими (например, объект другого довольно здоровенного класса), и у вас есть некоторая внешняя подпрограмма, которая работает только со ссылками на объекты этого класса. Вы не хотите копировать объект-член, так что это позволяет вам передавать его.

...