Ответ 1
Оригинальный ответ:
потому что функция-член не является функцией, а указатель-функция-функция не является указателем на функцию. Поэтому правила распада не применяются.
Кроме того, существует тип функции в С++, но не тип член-функции. Таким образом, вы можете использовать функцию в тех местах, где ожидается от указателя к функции, но вы не можете использовать функцию-член, потому что нет такой вещи, только функция-указатель-член. f в вашем примере - это функция. С другой стороны, Fred:: f... ну, ничего.
Кроме того, я бы сказал, что "имя функции может распадаться...". Нет, имя ничего не может сделать, lvalue типа функции может быть неявно преобразовано в указатель-к-функции, и это преобразование идентичности в отношении разрешения перегрузки
Редактирование, чтобы уточнить мой ответ:
Каждое выражение в С++ имеет тип и значение. Значение одного типа иногда может быть преобразовано в значение другого типа. Эти преобразования оцениваются так, чтобы сделать одно преобразование лучше, чем другое, в основном для разрешения функции перегрузки.
Один из типов преобразований называется преобразованием lvalue-to-rvalue. Когда lvalue появляется в контексте, где требуется rvalue, это преобразование имеет место. Обычно такой вид преобразования ничего не делает, например:
int i = 4, j = 5;
i = j;
на второй строке j является lvalue, но здесь требуется r значение, поэтому j преобразуется в r-значение. Но это не наблюдаемое обращение, не так ли? Но бывают случаи, когда можно наблюдать преобразование lvalue-to-rvalue. То есть lvalue массива n T может быть преобразовано в rvalue типа T*
, значение которого является адресом первого элемента массива и функции lvalue type "с сигнатурой S" rvalue типа "указатель на функцию с сигнатурой S", значением которой является адрес функции
Это означает, что когда мы назначаем функцию указателю на функцию, функция lvalue неявно преобразуется в адрес.
void f() {}
void (*p) () = f; //f is converted to rvalue
f является выражением и имеет тип. f type void()
В С++ такого типа нет, как member-function
Существуют указатели-на-члены-функции, но не сами функции-члены. Я говорю, конечно, о нестатических функциях. Статические функции работают так же, как обычные функции, т.е. Вам не нужно писать &X::f
, вместо этого вы можете написать X::f
Зачем? Поскольку X:: f имеет функцию типа и имеет место вышеупомянутое преобразование. Если f нестатически, X:: f имеет тип... что? О да, у него нет типа и, следовательно, не является выражением и поэтому не имеет значения, и поэтому это значение не может быть преобразовано ни в что.
Цитата из стандарта: 5.3.1 пункт 3 Указатель на член формируется только тогда, когда явный и используется, а его операнд - это идентификатор, не заключенный в круглые скобки. [Примечание: то есть выражение & (qualified-id), где идентификатор с квалификацией заключен в круглые скобки, не образует выражение типа "указатель на элемент". Также не имеет идентификатор-идентификатор, потому что нет никакого неявного преобразования из квалифицированного идентификатора для нестатической функции-члена в тип "указатель на функцию-член", поскольку от lvalue типа функции от типа "указатель на функцию" (4.3)). Не является & unqualified-id указателем на члена, даже в рамках неквалифицированный класс. ]
Надеюсь, что это было яснее...