Эзотерические операторы на C++
Какова цель следующих эзотерических операторов С++?
Указатель на член
::*
Привязать указатель к элементу указателем
->*
Привязать указатель к элементу по ссылке
.*
(ссылка)
Ответы
Ответ 1
Указатель на элемент позволяет иметь указатель, относящийся к определенному классу.
Итак, скажем, у вас есть контактный класс с несколькими номерами телефонов.
class contact
{
phonenumber office;
phonenumber home;
phonenumber cell;
};
Идея заключается в том, что если у вас есть алгоритм, который должен использовать номер телефона, но решение о том, какой номер телефона следует делать за пределами алгоритма, указатели на участника решают проблему:
void robocall(phonenumber contact::*number, ...);
Теперь вызывающий объект robocall может решить, какой тип номера звонков использовать:
robocall(&contact::home, ...); // call home numbers
robocall(&contact::office, ...); // call office number
.*
и ->*
вступают в игру, если у вас есть указатель. Итак, внутри robocall вы бы сделали:
contact c = ...;
c.*number; // gets the appropriate phone number of the object
или
contact *pc = ...;
pc->*number;
Ответ 2
Нет такого оператора, как ::*
, и его никогда не было. Я не знаю, где вы его получили.
Что касается ->*
и .*
- это операторы разыменования для указателей типа указателя на член.
struct S {
int i;
};
int main() {
int S::*pi = &S::i; // pointer of pointer-to-member type
S s;
S* ps = &s;
s.*pi = 0; // operator `.*` used
assert(s.i == 0);
ps->*pi = 1; // operator `->*` used
assert(s.i == 1);
}
Что касается каких-то указателей к членам... что говорит ваша любимая книга на С++ по этому вопросу?
Ответ 3
Они относятся к указателям-к-членам и указателям-к-членам-функциям.
struct Foo {
int a() { return 1; }
int b() { return 2; }
int c;
};
int main() {
Foo f;
f.c = 3;
typedef int (Foo::*member_fn)(); // pointer-to-member-function
typedef int (Foo::*data_member); // pointer-to-member
member_fn mf = &Foo::a;
(f.*mf)(); // calls the member function pointed to by mf. returns 1
mf = &Foo::b;
(f.*mf)(); // This time, returns 2, since mf points to b
Foo *fp = &f;
(fp->*mf)(); // same thing, via pointer to f instead of object/reference f.
data_member dm = &Foo::c;
f.*dm; // is 3
f.*dm = 5;
f.c; // is now 5.
Foo f2; // another instance
f2.c = 12;
f2.*dm; // is 12. Same pointer-to-member, different object.
}
Хотя он может выглядеть как один, ::*
не является оператором. Это оператор ::
и оператор *
operator рядом друг с другом. Чтобы доказать это, не прибегая к чтению стандарта, попробуйте добавить пробелы: :: *
компилирует, . *
нет, также -> *
.
Что они действительно полезны для того же принципа, что и указатели на функции. Вы не использовали бы их, как я уже выше, в ситуации, когда вы могли бы просто вызвать функцию по имени, но вы можете передать их в качестве параметров или вернуть их из функций, сохранить их или выбрать один из нескольких на основе сложной логики.
Если это помогает, я считаю, что синтаксис выбран так, что хотя .*
является неделимым одиночным оператором, вы можете себе представить, что *dm
"означает" c
, член, на который указывает dm. Поэтому, если dm
указывает на c
, то f.*dm
совпадает с f.c
.
Ответ 4
Обратите внимание на С++ FAQ Lite раздел по указателям на функции-члены. Найдите конкретные "операторы", о которых вы говорите (в большинстве браузеров Ctrl-F открывает диалог поиска/поиска, который позволяет вам искать текст на веб-странице), и это должно помочь вам лучше понять ситуацию.
Ответ 5
Упрощенный ответ - эти операторы позволяют назвать функции-члены "регулярными" функциями (по крайней мере, они выглядят одинаково с точки зрения конечного пользователя). Пример реального мира - они много используются в различных реализациях обратного вызова.
Ответ 6
Это позволяет вам указывать на функции-члены (и переменные-члены), привязанные к определенному экземпляру класса.
Указатели на функции-члены могут быть полезны для таких вещей, как легкие реализации шаблона состояния. Как правило, в любое время, когда вы хотите изменить поведение объекта с течением времени, не прибегая к отключению всего объекта, вы можете рассмотреть использование указателей для функций-членов.
Указатели на переменные-члены могут использоваться, если вы хотите, например, реализовать общий алгоритм для поиска массива структур для записи, которая имеет конкретное значение для данного поля.