Разница в том, что вы не можете создавать объекты типа функции, но вы можете создавать объекты типа указатель и функцию ссылка тип.
Это означает, что если у вас есть функция, скажите f()
как:
void f(){}
, тогда вот что вы можете сделать, а что нет:
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
Тестовый код:
typedef void (&FunctionTypeR)();
typedef void FunctionType();
void f(){}
int main() {
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
return 0;
}
Теперь посмотрите на ошибку компиляции (и предупреждения):
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: function ‘void fun1()’ is initialized like a variable
prog.cpp:8: warning: unused variable ‘fun2’
prog.cpp:9: warning: unused variable ‘fun3’
Демонстрационная версия онлайн: http://ideone.com/hpTEv
Однако, если вы используете FunctionType
(который является типом функции) в списке параметров функции как:
void foo(FunctionType bar);
, то это эквивалентно
void foo(FunctionType * bar);
Это означает, что неважночто вы пишете, вы можете вызвать функцию, используя bar
как:
bar(); //ok
(*bar)(); //ok
То есть вы можете написать это:
void h(FunctionType fun) { fun(); }
void g(FunctionType fun) { (*fun)(); }
Демо: http://ideone.com/kwUE9
Это связано с типом функции для настройки указателя типа функции ;то есть тип функции настроен на , чтобы стать указателем на тип функции :
Function type | Function pointer type (adjusted type)
void () | void (*)()
void (int) | void (*)(int)
int (int,int) | int (*)(int,int)
.... | ... so on
Стандарт C ++ 03 говоритв §13.1 / 3
Объявления параметров, отличающиеся только тем, что один является типом функции, а другой является указателем на один и тот же тип функции, эквивалентен . То есть тип функции настраивается, чтобы стать указателем на тип функции (8.3.5) .
[Example:
void h(int());
void h(int (*)()); // redeclaration of h(int())
void h(int x()) { } // definition of h(int())
void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
И если вы используете `FunctionTypeR
(который являетсяфункция ссылка тип) как:
void foo(FunctionTypeR bar);
, то это эквивалентно:
void foo(FunctionType * & bar);
И,
void h(FunctionTypeR fun) { fun(); }
void g(FunctionTypeR fun) { (*fun)(); }
Демонстрация: http://ideone.com/SmtQv
Интересная часть ...
Вы можете использовать FunctionType, чтобы объявить функцию (но не определить ее).
ДляНапример,
struct A
{
//member function declaration.
FunctionType f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
//forward declaration
FunctionType h; //equivalent to : void h();
int main() {
A a;
a.f(); //call member function
h(); //call non-member function
}
void h() //definition goes below main()
{
std::cout <<"hmmm.." << std::endl;
}
Демо: http://ideone.com/W4ED2