передать функцию по значению (?) вместо указателя функции? - PullRequest
10 голосов
/ 18 августа 2011

Извините, если раньше об этом спрашивали, но я не смог его найти.

Поэтому я пытаюсь узнать о шаблонах и новых возможностях C ++ 11 (в основном лямбда-выражения, что мне всегда нравилось вдругие языки).

Но в своих тестах я пришел к чему-то, что я понятия не имел, что это работает, и я пытаюсь понять, как это работает, но не могу понять это ..

Следующееcode:

template <class Func>
void Test( Func callback ) {
    callback( 3 );
}

void Callback( int i ) {
    std::cout << i << std::endl;
}

int main( int argc, char** argv ) {
    Test( &Callback ); // this I was expecting to work, compiler will see its a pointer to a function
    Test( Callback ); // this also works, but how?!
    return 0;
}

Если я понимаю, как работают шаблоны, то в основном это схема для компилятора, чтобы знать, что собирать, поэтому первый вызов Test( &Callback ); Я ожидал, что сработает, потому что компилятор увидитшаблон получает адрес функции и предполагает, что аргументы должны быть указателями.

Но что за второй вызов?Что это за шаблон, если он есть?Копия функции (если это вообще имеет смысл)?

Ответы [ 4 ]

15 голосов
/ 18 августа 2011

Функция неявно преобразуется в указатель на себя; это преобразование происходит почти везде. Test(Callback) точно так же, как Test(&Callback). Нет никакой разницы. В обоих случаях Func определяется как void(*)(int).

Указатели на функции странные. Вы можете узнать больше о них в «Почему все эти сумасшедшие определения указателей на функции работают?»

3 голосов
/ 18 августа 2011

В C ++ функции не являются первоклассными объектами, что означает, что «функция как значение» не имеет в этом смысла. Вот почему имя функции всегда было неявно преобразовано в указатель на него.

2 голосов
/ 18 августа 2011

Функции неявно преобразуются в указатели на функции. Если факт, нет способа получить значение функции или ссылку. Как ни странно, вы можете создать тип значения функции, но вы не можете ничего ему присвоить.

Вот фрагмент кода , который демонстрирует, как лямбды и различные обратные вызовы реагируют на шаблоны.

0 голосов
/ 20 октября 2011

В C ++ 11 (и boost, и tr1) у нас есть std :: function как тип шаблона для хранения функторов, лямбд и функций.Таким образом, вы, безусловно, можете иметь концепцию хранения значения функции в переменной типа std :: function.эта переменная также может быть «пустой», что означает, что в ней не хранится функция (ссылка).Тогда он не может быть вызван.

Исходный вопрос касается того, что в отличие от C, C ++ допускает ссылки на функции.Кроме того, по причинам совместимости с C имя функции может вырождаться в указатель на функцию.Но из-за перегрузки вещи в C ++ более «интересны», чем в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...