У меня проблема с пониманием синтаксиса С++ в сочетании с указателями функций и декларациями функций, то есть:
Обычно, когда мы хотим объявить тип функции, мы делаем что-то вроде:
typedef void(*functionPtr)(int);
и это прекрасно для меня. С этого момента functionPtr является типом, который представляет указатель на функцию, которая возвращает void и принимает значение int в качестве аргумента.
Мы можем использовать его следующим образом:
typedef void(*functionPtr)(int);
void function(int a){
std::cout << a << std::endl;
}
int main() {
functionPtr fun = function;
fun(5);
return 0;
}
И мы получаем 5
, напечатанную на экране.
у нас есть указатель на функцию fun
, мы назначаем некоторый существующий указатель на функцию - function
, и мы выполняем эту функцию указателем. Круто.
Теперь, когда я читаю в некоторых книгах, функция и указатель на функцию обрабатываются как-то одинаково, поэтому на самом деле после объявления функции function()
каждый раз, когда мы говорим о функции, мы имеем в виду действительную функцию и указатель на функцию того же типа, поэтому следующие компиляции и каждая команда дают тот же результат (5 напечатаны на экране):
int main() {
functionPtr fun = function;
fun(5);
(*fun)(5);
(*function)(5);
function(5);
return 0;
}
Итак, пока я могу себе представить, что указатели на функции и функции почти одинаковы, тогда это как-то прекрасно для меня.
Тогда, хотя, если указатель на функцию и действительную функцию одинаков, то почему я не могу сделать следующее:
typedef void(functionPtr)(int); //removed *
void function(int a){
std::cout << a << std::endl;
}
int main() {
functionPtr fun = function;
fun(5);
return 0;
}
Это дает мне следующую ошибку:
prog.cpp: 12: 14: warning: Объявление 'void fun (int)' имеет 'extern' и инициализируется functionPtr fun = function;
Поэтому я понял, что по какой-то причине компилятор теперь понимает, что забава - это уже существующая функция. Затем я попробовал следующее:
int main() {
functionPtr fun;
fun(5);
return 0;
}
И у меня возникла ошибка связи. Я как-то понимаю, что, поскольку компилятор теперь обрабатывает удовольствие как уже существующую функцию, то из-за того, что забава нигде не определена, я получаю ошибку связывания. Поэтому я изменил имя переменной:
typedef void(functionPtr)(int);
void function(int a){
std::cout << a << std::endl;
}
int main() {
functionPtr function;
function(5);
return 0;
}
Итак, теперь функция main name используется в основной тени, поэтому function(5)
используется из объявления functionPtr function;
. Он отлично работает и печатает 5 на экране.
Итак, теперь я в шоке. Почему это случилось? Также вводит в заблуждение, что когда указатель функции объявляется следующим образом:
typedef void(*functionPtr)(int);
Я могу создать функцию типа functionPtr следующим образом:
functionPtr function(int a){
std::cout << a << std::endl;
}
тогда как при объявлении чего-то вроде:
typedef void(functionPtr)(int);
делает следующее:
functionPtr function(int a){
std::cout << a << std::endl;
}
интерпретируется компилятором как функция, возвращающая функцию. Если это так, то почему предыдущее объявление (typedef void(functionPtr)(int);
) знало, что это функция, возвращающая void и не возвращающая функцию functionPtr?
Может ли кто-нибудь объяснить мне, что на самом деле происходит для меня?
Я использую g++ С++-компилятор с включенной опцией С++ 14.