2011-08-01 54 views
7

typedef int (&rifii) (int, int)将用于什么?C++语法/语义问题:引用函数和typedef关键字

这个“声明”之前的typedef是做什么的? 我想认为这是

typedef (int (&rifii) (int, int)) [new name] 

但[新名称]是不存在一样,如果你对下面的语法做

typedef int INTEGER; 

类似的问题:

typedef void (*PF)(); 

PF edit_ops[ ] = { &cut, &paste, &copy, &search }; 
PF file_ops[ ] = { &open, &append, & close, &write }; 

PF* button2 = edit_ops; 
PF* button3 = file_ops; 

button2[2](); 

什么typedef是否允许?难道使得它,这样你就不必键入:

void (*PF)(); 
(void (*PF)()) edit_ops[ ] = { &cut, &paste, &copy, &search }; 
(void (*PF)()) file_ops[ ] = { &open, &append, & close, &write }; 

(void (*PF)())* button2 = edit_ops; 
(void (*PF)())* button3 = file_ops; 

如果是发生了什么的第二部分([你想要什么])中的typedef像:

typedef [what you have -- (FP)] [what you want] 

澄清此事不胜感激。

+0

http://stackoverflow.com/questions/1591361/understanding-typedefs-for-function-pointers-in-c-examples -hints-and-tips-plea – vines

+0

这个问题是类似的,我在发帖之前仔细查看了相关主题,但是我的问题是特定的,我无法从其他帖子推断出答案。 –

回答

16

Typedef不能像typedef [type] [new name]那样工作。 [new name]部分并不总是结束。

你应该这样看待它:如果[some declaration]声明一个变量,typedef [same declaration]会定义一个类型。

例如:

  • int x;声明了一个名为x int类型的变量 - >typedef int x; 定义一种类型x作为INT。
  • struct { char c; } s;定义了一个结构类型为s的变量 - >typedef struct { char c; } s;将类型s定义为某个结构类型。
  • int *p;声明了一个名为p类型指针的变量int - > typedef int *p;定义了一个类型p作为指向int的指针。

并且:

  • int A[];声明了一个名为整数数组A - >typedef int A[];声明一个类型A作为整数数组。
  • int f();声明一个名为f - >typedef int f();的函数声明一个函数类型f返回一个int并且不带任何参数。
  • int g(int);声明一个函数名g - >typedef int g(int);声明一个函数类型g返回一个int并取一个int。

顺便说一句:请注意,所有函数参数都在新名称之后!由于这些类型也可能很复杂,所以在[新名称]之后可能会有很多文本。可悲的是,但是的确如此。

但是那些功能不正确指针还有,只是函数类型。我不确定C或C++中是否存在函数类型,但作为解释中的中间步骤很有用。

要创建一个真正的函数指针,我们必须给名称添加'*'。其中,可悲的是,有错误的优先级:

  • typedef int *pf();声明的函数型PF为返回INT *。糟糕,这不是预期的。

因此,使用()来组:

  • typedef int (*pf)();声明的函数指针类型PF为返回一个int和不接受参数。
  • typedef int (&rf)();声明一个函数引用类型rf返回一个int并且不带任何参数。

现在让我们来看看你的例子,并回答您的问题:

typedef int (&rifii) (int, int);声明的函数引用类型rifii为返回一个int,并采取两个int参数。

显然(?)button2[2]();将会拨打copy();

的typedef不正确的语法是很难正确地写没有编译器和硬盘即使有编译器来阅读:

void (*edit_ops[])() = { &cut, &paste, &copy, &search }; 
void (*file_ops[])() = { &open, &append, & close, &write }; 

void (**button2)() = edit_ops; 
void (**button3)() = file_ops; 

button2[2](); 

这就是为什么每个人都使用函数指针时喜欢的typedef。

阅读时,找到开始阅读的地方。尽可能多地阅读正确的内容,但通过()观察分组。然后尽可能多地阅读,再次受限于分组()。完成()中的所有内容后,从右边开始阅读,然后再阅读。

应用于void (*edit_ops[])(),这意味着

  1. edit_ops是 (转到右侧)
  2. 阵列 (命中的组的端部,所以向左转)
  3. 的指针 (分组的末尾)
  4. 采取 一个函数(解析()向右)
  5. 没有argume NTS (向左走)
  6. 返回一个空

对于专家: 为了使它更加复杂,参数可以有名字(这将被忽略),所以它甚至可能是很难找到从哪里开始解析!例如。 typedef int (*fp)(int x);有效且与typedef int (*fp)(int);一样有名称甚至可以在它们周围有():typedef int (*fp)(int (x));但正如我们所看到的,参数名称可以省略,因此即使允许以下条件:typedef int (*fp)(int());。这仍然是一个函数指针,它接受一个int并返回一个int。如果你想让你的代码真的很难阅读...

+0

你的解释是帮助。澄清:typedef void(* PF)();声明一个类型(* PF),它被定义为一个函数指针,它接受0个参数并且什么都不返回。所以现在我们有一个类型PF,如果我们可以在我们的表达式中使用它(我可能会声明语句),比如PF edit_ops [] = {。没有定义“新类型”,我们使用void(* edit_ops [])()= {...}。这就是说我们正在创建一个函数指针数组,它可以是...?这个表达式的类型是一个函数指针吗? –

+0

@Matthew:是的,'void(* edit_ops []()= {...};定义一个函数指针数组,并用值'cut','paste','copy'和'search'来初始化这个数组。 void(** button2)()= edit_ops;'声明一个指向该数组的第零个元素的指针。 'button2 [2]();'使用数组的第三个元素并调用它指向的函数。这恰好是“复制”。 – Sjoerd

+0

@Matthew:在你的第一句话中,'typedef void(* PF)()'声明了一个'PF'类型,* not *'(* PF)'。 'PF'已经是一个指针了。最后一个语句void(* x [])()= ...'声明'x'是一个函数指针数组。 –

-1

编辑:对不起,首先回答没有初始化fcn ptr。

typedef int(& rifii)(int,int)允许您声明通过引用返回int并将两个int作为参数的函数指针。

rifi x,y,z; 

int &ret_an_int_ref(int p1, int p2) { 
    static int retval=0; 
    if(p1 > p2) retval = p1*p2; 
    return retval; 
} 

    x = ret_an_int_ref; 
    y = ret_an_int_ref; 

int & an_int_ref = x(1,2); 
int & another_int_ref=y(3,4); 

z = x; 

z(1,2); // will give the same answer as x(1,2); 
+0

那么rifi现在是一种类型?变量x,y和z是那种类型?据Bjarne说,从函数返回一个参考是一种罪过,所以我假设我永远不会看到这个? –

+0

我不能100%肯定地说rifi是否是一个“类型”,希望上师能够参与进来。它的行为就像一个类型,可以像类型一样传递,并可能用作模板参数。你很可能永远不会看到这一点,但有时对于复杂的数据类型,最好由ref返回。并且operator =应该总是通过ref返回,以便像A = A这样的哑语不会导致seg错误。 –

+0

该函数不返回对int的引用,但是它是对返回(普通)int的函数的引用。你的版本应该是'typedef int&(rifii)(int,int);' – Sjoerd

5

此:

typedef int (&rifii) (int, int); 

创建名为rifii的typedef,这是一个函数,它有两个整数和返回一个整数。这是用于声明函数typedefs的typedef语法。所以,如果你有一个函数:

int SomeFunc(int a, int b); 

您可以将其存储在该类型定义:

rifii varName = SomeFunc; 

后来称之为:

varName(1, 3); 

所以,如果你申报的rifii阵列,你所拥有的是一系列对所有具有相同签名的函数的引用。你的typedef是一个指针函数,它不接受任何参数,也不返回任何内容,所以它们的数组是不带参数且不返回任何内容的函数的数组。基本上,由于C/C++函数命名的奇怪,typedef名称(您正在为其创建typedef的名称)位于函数类型的中间。这很奇怪,但你已经习惯了。