2013-07-15 141 views
-1

我正在学习有关函数指针和整个下面的代码来:函数指针/函数表

#include <iostream> 
using namespace std; 

// A macro to define dummy functions: 
#define DF(N) void N() { \ 
    cout << "function " #N " called ... " << endl; } 

DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); 

void (*func_table[])() = {a, b, c, d, e, f, g}; 

int main(){ 
    while(1){ 
     cout << "press a key from 'a' to 'g' " 
     "or q to quit"<< endl; 
     char c, cr; 
     cin.get(c); cin.get(cr); // second one for CR 
     if (c == 'q') 
     break; 
     if (c < 'a' || c > 'g') 
     continue; 
     (*func_table[c-'a'])(); 
    } 
} 

可有人请向我解释如何将函数指针func_table作品?特别是在{}中有a,b,c,d,e,f,g的效果以及整个表达式在做什么?

通常,当我看到指向函数的指针时,通过指定函数名称来初始化指针,但在本例中仅提供了一个字符数组。那么它怎么知道调用DF(char)?

另外,我不知道为什么我需要有语句:

DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); 

而且,用下面的语句:(*func_table[c-'a'])(); 为什么我们要减去“A”是因为不同将决定正确的原因信可以从阵列中选择{a,b,c,d,e,f,g}

回答

1

这是一些丑陋的,模糊的代码,它不是让你感到困惑的耻辱。让我们开始吧一块一块:

// A macro to define dummy functions: 
#define DF(N) void N() { \ 
    cout << "function " #N " called ... " << endl; } 

DF(a); 

如果您展开宏调用,您可以:

void a() { 
    cout << "function a called ... " << endl; } 

而对于B,C等类似。所以ag都是打印自己名字的函数,仅此而已。

void (*func_table[])() = {a, b, c, d, e, f, g}; 

这是更容易的类型定义为:

typedef void (*FuncPtr)(); //FuncPtr is a function pointer to functions of type void X(); 
FuncPtr func_table[] = {a, b, c, d, e, f, g}; 

而实际上,这是{&a, &b, &c, &d, &e, &f, &g} - 笔者利用隐函数到函数指针的转换。含义:func_table是函数指针到a阵列通过g

int main(){ 
    while(1){ 
     cout << "press a key from 'a' to 'g' " 
     "or q to quit"<< endl; 
     char c, cr; 
     cin.get(c); cin.get(cr); // second one for CR 
     if (c == 'q') 
     break; 
     if (c < 'a' || c > 'g') 
     continue; 

这应该是清楚的。现在呼叫:

(*func_table[c-'a'])(); 

c-'a'是从'a'偏移,对于“A”意为0,1为“B”等等。例如,如果c是'd',该行将调用(*func_table['d'-'a'])(),这是*(func_table[3])(),这只是d - 因此该行只是用您刚输入的名称调用该函数。

+1

我想我现在明白了。因此宏#define DF(N)void N(){/ ....将创建一个名称为(N)的新函数,所以DF(a)= a()。因为我们将没有参数列表的函数名传递给函数指针,这就是为什么我们有函数{a,b,c,d,e,f,g}的数组,这些函数实际上是{a(),b() ,c(),d(),e(),f(),g()} 感谢您的耐心和乐意解释我真正感激它的代码。 - Marco – SeekingAlpha

+0

不要让任何人抓到你写这样的代码;-) –

+1

实际上,函数指针数组是'{&a,&b,&c,&d,&e,&f,&g}' - 作者利用隐式函数到函数指针的转换。 '{a(),b(),c()}'是一个函数调用结果的数组。 –

0

这条线:

#define DF(N) void N() { \ 
    cout << "function " #N " called ... " << endl; } 

定义名称为N一个新的功能。这工作,因为宏只需创建一个文本替换,所以当编译器看到它,它看到一个完全有效的函数名称为N,因为如果你输入的功能

void a() {\... } 

这里有函数声明与上面的宏,名为a-g

DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); 

这里:

void (*func_table[])() = {a, b, c, d, e, f, g}; 

上述声明的函数是简单分配。

您减去字符的原因是为函数数组获取索引0-n。

0

通常当我看到一个指向函数的指针,你通过指定函数名初始化指针 ,但在这个例子仅仅是 设有一个字符数组。那么如何知道致电 DF(char)?

实际上,它没有给出一个字符数组,而是一个函数数组。 DF(a)将定义一个函数nammed a。所以基本上,你最终有一个函数指针数组指向你的函数(即,a,b,c,...)的数组。

我们减少'a'的原因是因为,如果用户按下了b键,我们需要调用b函数。 您的变量c将具有“b”作为值。 'b' - 'a'= 1.因此它会调用你的数组的第二个函数指针,(因为array [1]是第二个元素),这实际上是函数名称b

0

丑丑...

DF(N)创建函式N输出 “N”(在宏使用#操作者)

这样:

DF(a); 

是写

较短方式
void a(){cout << "function Acalled" << endl;} 

现在他们存储在一个数组中:

func_table[0]() 

相当于

a() 

使用字符c-'a'正在做两个字符之间的差异:'a' - 'a' = 0

调用然后func_tables[c-'a']将调用预期的功能。