Ссылка на синтаксис функции - с и без & - PullRequest
8 голосов
/ 06 сентября 2011

Какая разница между

typedef void (&FunctionTypeR)();

против

typedef void (FunctionType)();

Второй также является ссылкой на функцию? FunctionTypeR эквивалентно FunctionType& при использовании в качестве типа аргумента?

Для

void foo(FunctionType bar)

Делает ли среда выполнения копию панели аргументов (функции) при вызове foo?

1 Ответ

13 голосов
/ 06 сентября 2011

Разница в том, что вы не можете создавать объекты типа функции, но вы можете создавать объекты типа указатель и функцию ссылка тип.

Это означает, что если у вас есть функция, скажите 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

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