Если я могу взять нормальный указатель на переменную в классе, какой смысл указателей членов класса? - PullRequest
1 голос
/ 10 октября 2010

Возьмите этот код:

struct mystruct
{
    int var;

    mystruct() : var(0) {}
};

int main()
{
    mystruct ins;

    int* p = &ins.var;

    *p = 1;
}

Так, каковы конкретные действительно хорошие примеры использования указателя на член класса?

int    X::*p = &X::data; /* p contains offset */
X      object;
X      *objptr = new X;

int    i = object.*p;
int    j = objptr->*p;

Ответы [ 3 ]

8 голосов
/ 10 октября 2010

Похоже, ваш вопрос касается указателей типа указателя на data -member. В C ++ также есть указатели типа указатель на член- function . У обоих есть что-то общее на каком-то абстрактном уровне, но в остальном они разные.

Указатель типа указатель на элемент-член данных применим к любому экземпляру класса. Обычный указатель всегда указывает на член конкретного экземпляра класса. Указатель типа указатель на элемент-член является реализацией более высокого уровня идеи «смещения во время выполнения» от начала объекта класса. Это относительный указатель. Таким образом, это совершенно отличная вещь от обычных указателей, которые являются абсолютными указателями.

Чтобы проиллюстрировать это на примере, скажем, у вас есть массив классов с тремя членами одного типа x, y и z

struct Point { int x, y, z; };

Point point_array[N];

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

void zero_members(Point points[], int n, int Point::*m) {
  for (int i = 0; i < n; ++i)
    points[i].*m = 0;
}

Теперь с помощью этой функции вы можете сделать

zero_members(point_array, N, &Point::x);

для установки всех x с на ноль. Или вы можете сделать

zero_members(point_array, N, &Point::y);

для установки всех y на ноль. Все это можно сделать с помощью функции single , и, что также важно, выбор элемента выполняется параметром run-time (в отличие от время компиляции один).

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

3 голосов
/ 10 октября 2010

Так что вы можете получить доступ к члену в нескольких случаях.

1 голос
/ 10 октября 2010

Хм, это похоже на запрос хороших примеров использования goto ... ;-) Хорошо, оно есть, и иногда это может быть удобно, но любой пример "хорошего" использования goto вероятен быть спорным И так же для указателей членов, они довольно низкоуровневые.

Для указателей на функции-члены обычно используется система, управляемая событиями. Упакуйте указатель на функцию-член вместе с указателем на объект соответствующего класса, и вы получите нечто очень похожее на делегат C #. Затем вы можете передать этот маленький пакет функтора и чужой код, например, графический интерфейс, может перезвонить на ваш объект, даже не зная об этом.

Библиотека Boost обеспечивает некоторую поддержку, например, boost::function и boost::bind, как и TR1 и будущая стандартная библиотека C ++ 0x (по сути, подмножество функций Boost).

Хотя я не могу придумать, как часто используются указатели на элементы данных.

Что касается "низкого уровня", указатели участников следуют особым правилам, которые позволяют непреднамеренно обойти ограничение доступа protected.

Приветствия & hth.,

- Альф

...