Указатель функции участника
-
25-09-2019 - |
Вопрос
Если следующее из FAQ C ++ FAQ Lite является true: «Название функции распадается к указателю на функцию» (в качестве названия имени массива к указателю на свой первый элемент); Почему мы должны включить Ampersand?
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;
И не только:
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;
Во втором случае Фреда :: F - это функция и может распадаться к указателю на эту функцию.
Я надеюсь, что этот вопрос не тот глупый.
Решение
Оригинальный ответ:
Поскольку функция элемента не является функцией, и указатель функции элементов не является указателем функции. Поэтому правила распада не применяются.
Кроме того, есть тип функции в C ++, но не тип функции элементов. Таким образом, вы можете использовать функцию в местах, где ожидается функция указателя, но вы не можете использовать функцию элемента, потому что нет такой вещи, только указатель-элемент-элемент. F В вашем примере является функция. С другой стороны, Фред :: Ф ... ну, ничего.
Кроме того, я бы утвердовал, что «имя функции может распадаться ...». Нет, имя ничего не может сделать, Lvalue типа функциональности может быть неявно преобразован в указатель-функцию, и это преобразование идентификатора, насколько связано с разрешением перегрузки.
Редактирование, чтобы уточнить мой ответ:
Каждое выражение в C ++ имеет тип и значение. Значение одного типа может периодически преобращаться в значение другого типа. Эти преобразования ранжируются так, чтобы сделать одно преобразование лучше, что еще один в основном для разрешения на функцию перегрузки.
Одним из типов конверсий называется преобразованием Lvalue-To-RValue. Когда в контексте появляется Lvalue, где требуется rvalue, это преобразование имеет место. Обычно этот вид преобразования ничего не делает, например:
int i = 4, j = 5;
i = j;
На второй строке j - это Lvalue, но здесь требуется rvalue, поэтому j преобразуется в rvalue. Но это не наблюдаемое преобразование, не так ли? Но есть случаи, когда можно соблюдать преобразование Lvalue-o-RValue. То есть, Львале массива N T может быть преобразован в rvalue типа T*
чья ценность является адресом первого элемента массива а также Функция Lvalue типа "с указателем Signature s" rvalue типа "типа" для функции с подписью s ", значение которой является адрес функции
Это означает, что, когда мы присваиваем функцию указывающей функцией, функция Lvalue неявно преобразуется в адрес.
void f() {}
void (*p) () = f; //f is converted to rvalue
f - это выражение и имеет тип. тип f void()
Такого типа в C ++ нет как member-function
Есть указатели-члены-функции, но не сами функции членов. Я говорю, конечно, о нестатических функциях. Статические функции работают так же, как обычные функции, то есть вам не нужно писать &X::f
, вместо этого вы можете написать X::f
Почему? Поскольку X :: F имеет функцию типа, и вышеупомянутое преобразование происходит. Если f нестатичен, однако, х :: F имеет тип ... что? О да, у него нет типа и, следовательно, не является выражением, и поэтому не имеет значения, и поэтому это значение не может быть преобразовано ни в чем.
Цитата из стандарта: 5.3.1 Пункт 3 Указатель на участник сформирован только тогда, когда используется явна и используется и его операнда является квалифицированным идентификатором, не заключенным в скобки. [Примечание. То есть выражение и (квалифицированный идентификатор), где квалифицированный идентификатор заключен в скобки, не образует экспрессию типа «указатель». Никто не имеет квалифицированного идентификатора, потому что нет никакого неявного преобразования из квалифицированного идентификатора для нестатической функции элементов к типу «указатель на функцию элементов», поскольку есть из типа Lvalue функций к типу «Указатель на функцию» (4.3 ). И нельзя и неквалифицировал - указатель для члена, даже в рамках класса неквалифицированного идентификатора. Несомненно
Надеюсь, это было яснее ...