#c
Вопрос:
Какова цель следующих эзотерических операторов C ?
Указатель на элемент
::*
Привязать указатель к элементу с помощью указателя
->*
Привязать указатель к элементу по ссылке
.*
(ссылка)
Комментарии:
1. Что бы ни говорила википедия,
::*
это не оператор.
Ответ №1:
Указатель на элемент позволяет иметь указатель, относящийся к определенному классу.
Итак, допустим, у вас есть класс контактов с несколькими телефонными номерами.
class contact
{
phonenumber office;
phonenumber home;
phonenumber cell;
};
Идея заключается в том, что если у вас есть алгоритм, который должен использовать номер телефона, но решение о том, какой номер телефона следует принимать вне алгоритма, указывает на то, как решить проблему:
void robocall(phonenumber contact::*number, ...);
Теперь абонент robocall может решить, какой тип телефонного номера использовать:
robocall(amp;contact::home, ...); // call home numbers
robocall(amp;contact::office, ...); // call office number
.*
и ->*
вступайте в игру, как только у вас появится указатель. Так что внутри robocall вы бы сделали:
contact c = ...;
c.*number; // gets the appropriate phone number of the object
или:
contact *pc = ...;
pc->*number;
Комментарии:
1. В InformIT есть читаемое руководство по указателям на участников .
2. Здесь есть хороший пример этого: msdn.microsoft.com/en-us/library/k8336763.aspx
3. Да, указатели на элементы довольно удобны — я широко использую их для сериализации в/из потоков байтов и наборов результатов базы данных. Вроде как заканчивается отражением бедняка. С помощью указателей на элементы (поля и методы) вы можете легко настроить структуры данных, которые позволяют динамически манипулировать типами с очень небольшим количеством статических знаний (обычно помогает иметь общую базу и некоторые доступные методы отправки в стиле посетителя).
Ответ №2:
Такого оператора нет ::*
и никогда не было. Я не знаю, где ты его взял.
Что касается ->*
и .*
— это операторы разыменования для указателей типа указатель на элемент.
struct S {
int i;
};
int main() {
int S::*pi = amp;S::i; // pointer of pointer-to-member type
S s;
S* ps = amp;s;
s.*pi = 0; // operator `.*` used
assert(s.i == 0);
ps->*pi = 1; // operator `->*` used
assert(s.i == 1);
}
Что касается того, что такое указатели на участников… что говорит по этому поводу ваша любимая книга на C ?
Комментарии:
1. Я получил ::* из википедии, указанной в качестве ссылки на мой вопрос.
2. ::* отлично компилируется в g .
3. @Neil G: Что именно «отлично компилируется в g «?
4.@Neil G:
::
является оператором, потому что так сказано в стандарте, и потому::
что токен играет роль оператора в синтаксисе C .::*
не является оператором, потому что стандарт не упоминает об этом, когда перечисляет операторы, и потому::*
что при анализе C нет маркера.int x = 5 -2;
компилирует, не означает-
, что является оператором.5. @Neil G: Во-первых,
::*
в ответе Сэмюэля нет оператора. Единственное место, где вы можете найти::*
его ответ (как и в моем), — это декларации. В объявлениях нет такого понятия, как «операторы», даже если что-то может выглядеть как оператор. Когда вы видитеint 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 = amp;Foo::a;
(f.*mf)(); // calls the member function pointed to by mf. returns 1
mf = amp;Foo::b;
(f.*mf)(); // This time, returns 2, since mf points to b
Foo *fp = amp;f;
(fp->*mf)(); // same thing, via pointer to f instead of object/reference f.
data_member dm = amp;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.
}
Хотя это может выглядеть так, ::*
это не оператор. Это ::
*
оператор и модификатор типа оператора рядом друг с другом. Чтобы доказать это, не прибегая к чтению стандарта, попробуйте добавить пробелы: :: *
компилирует, . *
не делает и не делает -> *
.
Что касается того, для чего они на самом деле полезны — тот же принцип, что и указатели функций. Вы бы не использовали их, как я описал выше, в ситуации, когда вы могли бы просто вызвать функцию по имени, но вы можете передать их в качестве параметров или вернуть их из функций, сохранить их или выбрать один из нескольких на основе сложной логики.
Если это поможет, я полагаю, что синтаксис выбран таким образом , что, хотя .*
это неделимый единый оператор, вы можете представить, что *dm
«означает» c
, элемент, на который указывает dm. Так что если dm
указывает на c
, то f.*dm
это то же f.c
самое, что и .
Ответ №4:
Ознакомьтесь с разделом C FAQ Lite, посвященным указателям на функции-члены. Найдите конкретные «операторы», о которых вы говорите (в большинстве браузеров Ctrl-F открывает диалоговое окно поиска/поиска, которое позволяет вам искать текст на веб-странице), и это должно помочь вам лучше понять ситуацию.
Ответ №5:
Упрощенный ответ — эти операторы позволяют вызывать функции-члены как «обычные» функции (по крайней мере, это выглядит одинаково с точки зрения конечного пользователя) . Пример реального мира — они часто используются в различных реализациях обратного вызова.
Ответ №6:
Они позволяют иметь указатели на функции-члены (и переменные-члены), которые привязаны к определенному экземпляру класса.
Указатели на функции-члены могут быть полезны для таких вещей, как облегченные реализации шаблона состояния. Как правило, в любое время, когда вы хотите изменить поведение объекта с течением времени, не прибегая к отключению всего объекта, вы можете рассмотреть возможность использования указателей на функции-члены.
Указатели на переменные-члены можно использовать, если вы хотите, например, реализовать универсальный алгоритм для поиска в массиве структур записи, имеющей определенное значение для данного поля.