(在我上传的资源中,可以找到应用下面技术的C++源代码)
函数指针一直以来是C 语言中的一个难点。什么情况下可以用函数指针?怎么用?下面给出一个简单的例子:
我们都知道数字电路中有 与门,或门,非门等逻辑电路,下面假设我们要画出他们的图形:
一般的程序员会这样写:
Void Draw(int type)
{
Switch(type)
{
Case AND:
DrawAnd();
Break;
Case OR:
DrawOr();
Break;
Case NOT:
DrawNot();
Break;
Default:
Break;
};
}
当type的种类达到几十个时,程序的效率就越来越低了。因为上面的语句编译器会解释成如下语句(最后一种情况要经过很多次判断才能执行到):
If(type==AND)
DrawAnd();
Else if(type==OR)
DrawOr();
Else if(type==NOT)
DrawNot();
………
为了提高效率,我们可以写成下面的方式:
typedef void (*DrawFunction)(void);/*定义函数指针类型*/
const DrawFunction pDrawFunction[ ] =
{
DrawAnd;
DrawOr;
DrawNot;
……
}
Enum
{
AND, OR, NOT, …….
}
Void Draw(int type)
{
pDrawFunction[ type ]( );
}
上面的代码在减少了代码量的情况下,反而提高执行效率。这就告诉我们程序员:空间换时间只是一个相对概念,不要理解成多的代码量一定能换取到运行时间。
那么C语言中的函数指针和C++中的虚函数有什么联系呢?
我刚开始写MFC程序时,总是想用C语言的函数指针的方法去实现类似上面的情况,但是,确连编译都通不过。后来,我才认识到,C++在自身的特性上就实现了类似上面的方法。C++的这种特性就是“虚函数”。
C++的书上,提到“虚函数”,一般会说“虚函数实在运行时动态绑定的,通过编译时生成的虚函数表,可以找到对应的函数”
这样的说法和上面的例子对应起来,就更好理解了。所谓虚函数表,就是形成了类似上面的一个数组(具体实现上应该没有这么简单),然后通过类的ID号,就可以定位到自己的函数了。
我们还是以上面为例,在C++中如何实现画图:
定义一个基类:
Class CItemBase : public CObject
{
Public :
Virtual void draw(void);
};
然后分别定一 CAnd, COr, CNot….
Class CAnd: public CItemBase
{
Public :
Virtual void draw(void);
}
Class COr: public CItemBase
{
Public :
Virtual void draw(void);
}
Class CNot: public CItemBase
{
Public :
Virtual void draw(void);
}
假设有一个指针数组CArray array;里面有And, Or, Not的三个实例,则可以这样画图:
CItemBase *p
Int cnt = array,GetCount();
For(int i=0; i<cnt; i++)
{
P = array.GetAt(i);
p->draw(); /*p 会在运行时自动找到对应的画图函数*/
}