加载中…
个人资料
Hill
Hill
  • 博客等级:
  • 博客积分:0
  • 博客访问:11,015
  • 关注人气:0
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

结构体与函数指针的特殊应用

(2007-06-12 23:38:17)
分类: 我的学术文章
     在C++中,我们很容易就可以实现函数重载,特别是类的同名方法(多态)。那么,在C语言中我们可以有类似的应用吗?
     呵呵,今天我找到了一种。
     下面先给出我的说明代码,再做解释:
//-----------------------------------------------------------//
#include <stdio.h>
struct A
{
    void* (*fun)();
};
void myfun1()
{
    printf("this is fun()\n");
}
int myfun2(int a)
{
    printf("this is fun(%d)\n",a);
    return a;
}

char myfun3(int a)
{
    printf("this is fun(%c)\n",a);
    return a;
}
int main()
{
    struct A a;
    a.fun=myfun2;
    printf("AAA  %d\n",a.fun());
    printf("AAA1  %d\n",a.fun(4));
    printf("AAA2  %d\n",a.fun(43,"32423"));

    a.fun=myfun3;
    printf("AAA  %d\n",a.fun());
    printf("AAA1  %d\n",a.fun(4));
    printf("AAA2  %d\n",a.fun(43,"32423"));
    return 0;
}

//-----------------------------------------------------------//
在GCC4.0下编译运行的结果如下:
//-----------------------------------------------------------//
hill@hill-laptop:~/Desk/temp$ gcc test4.c
test4.c: 在函数 ‘main’ 中:
test4.c:25: 警告: 从不兼容的指针类型赋值
test4.c:30: 警告: 从不兼容的指针类型赋值
hill@hill-laptop:~/Desk/temp$ ./a.out
this is fun(-1208768727)
AAA  -1208768727
this is fun(4)
AAA1  4
this is fun(43)
AAA2  43
this is fun(
AAA  -11
this is fun()
AAA1  4
this is fun(+)
AAA2  43
hill@hill-laptop:~/Desk/temp$
//-----------------------------------------------------------//

现在分析一下上面的代码:
首先,这个程序的思路是想用一个结构体模拟一个类,通过函数指针来申明“类”方法,并模拟多态性。
        void* (*fun)();--------(1)
是一个函数指针,注意,这里不要写成
        void (*fun)();--------(2)
接下来写了两个函数
    void myfun1();
    int myfun2(int);
在接下来的main函数中,我们为A实例a的fun域赋值,这里我们直接赋值了myfun2,若上面方法申明中采用(2),那么将不能把myfun2赋值给fun,因为void*是可以指向任何类型的指针,那么当然可以指向int。这里又定义了myfun3就是为类看看void*是否能自动的转化为char类型了。
    另外要说明的一点就是,调用a.fun时我实验了几种调用方法,如程序中所示,它对行参没有任何要求,在本例中,由于传入的是myfun2(int),若不加任何参数调用a.fun(),那么输入的int将随机而定;若参数多于两个,则只有第一个参数有效,其余参数被呼略掉;若第一个参数与所传入的函数不匹配,则虽然可以通过编译,但结果一般会与期望的不同(错误)。
    那么,它是否是多态呢?显然不是的,多态是个运行时概念,若想在C里面用同名函数则必须如此利用函数指针,在使用不同的重载形式前必须给函数指针赋上相应的函数才行,在本例中,若要用重载型myfun3的话,在调用a.fun(...)前必须有这样一行
    a.fun=myfun3;
这是因为C毕竟还是一个静态语言的原因。

    这种结构体与函数指针的结合使用还有很多用途,其实也可以将公用体与函数指针结合,方法一样。这几种结合功能相当强大。在定义接口时将非常有用。
    比如在写一个设备驱动程序时,我们就要填写一个数据结构file_operations,具体的定义如下:

struct file_operations {
int (*seek) (struct inode * ,struct file *, off_t ,int);
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);
int (*select) (struct inode * ,struct file *, int ,select_table *);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file *,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}
    这个数据结构为编程人员提供了一个访问设备的公用接口,比如read,write等等。
具体设备驱动程序的编写已经超出本文范围,日后再说明。

小结:
    利用函数指针来模拟多太,讨论出函数指针的一些特殊用法。以及调用函数指针的参数无关性。  

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有