处理函数和数组声明[条款17]---《C++必知必会》

时间:2022-09-13 16:17:47

  指向函数的指针声明和指向数组的指针声明容易混淆,原因在于函数和数组修饰符的优先级比指针修饰符的优先级高,因此通常需要使用圆括号。

  int *f1( );//一个返回值为 int* 的函数

  int ( *f2 )( );//一个指针,指向一个返回值为 int 的函数

  具有高优先级的数组修饰符存在同样的问题:

  const int N = 12;

  int *a1[ N ];//一个具有N个大小的数组,每个元素是 int *

  int ( *ap1 ) [ N ];//一个指针,指向一个具有N个 int 元素的数组

  理所当然,一旦拥有指向函数或数组的指针,就可以拥有指向这种指针的指针:

  int ( * * ap2 )[ N ];//一个指针,指向另一个指针,后者指向一个大小为N的 int 数组

  int * ( * ap3 )[ N ];//一个指针,指向一个大小为N的,每个元素为 int * 的数组

  int ( * * const fp2 )( ) =0; //一个常量指针,指向一个返回值为 int ,参数为空的函数指针

  注意,参数和返回值都会影响函数或函数指针的类型。

  char * ( *fp4 )( int ,int );

  char * ( *fp5 )( short , short )=0;

  fp4 = fp5;//错误!类型不匹配

  当函数和数组修饰符出现于同一个生命中时,事情的复杂性会变得难以估量。考虑入校常见但错误的声明,它试图声明一个函数指针数组:

  int ( * ) afp1[ N ];//语法错误!

  在以上错误的声明中,函数修饰符()的出现表示到了声明的末尾,而后面附加的afp1则表示一个语法错误的开始。这类似于一下数组声明写法:

  int [ N ] a2 ;//语法错误!

  这在Java中是合法的,但在C++中是非法的。函数指针数组的正确声明方式,是将数组名字和简单的函数指针声明放在一起。因此可以声明一个装有这些东西的数组:

  int ( * afp2 [ N ] ) ();//一个具有N个元素的数组,其元素类型为指向“返回值为int”的函数的指针

  至此,事情开始变得笨拙,typedef 闪亮登场的时刻到了:

  typedef  int ( * FP)()  ; //一个指向返回值为 int 的函数指针

  FP  afp3[ N ] ;// 一个具有N个“类型为FP”的元素的数组,该类型与afp2相同

  使用typedef可以简化复杂的声明语法,这也是对你代码维护者的关爱。使用typedef,甚至标准的set_new_handler函数的声明都变得简单多了:

  typedef void ( *new_handler )();

  new_handler set_new_handler( new_handler );

  如此一来,new_handler是指向这种函数的指针:它不带任何参数,返回void。而set_new_handler则是一个函数,带有一个new_handler作为参数,并返回一个new_handler作为结果。简单吧?如果尝试不用typedef,你的声望在哪些维护你的代码的人中将急剧下跌:

  void ( * set_new_handler( void (*)() ) ) ();//语法没错,但邪恶!

  还可以声明函数引用:

  int aFunc( double );

  int (&rFunc)( double ) = aFunc;

  函数引用很少用,其应用程度跟常量函数指针差不多:

  int (*const fFunc) (double) =aFunc;//常量函数指针

  数组引用确实提供了一些数组指针所未提供的额外能力,参见“数组形参[条款6]”中的讨论