Вопрос

Если следующее из 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 ). И нельзя и неквалифицировал - указатель для члена, даже в рамках класса неквалифицированного идентификатора. Несомненно

Надеюсь, это было яснее ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top