C语言实现多态的原理:函数指针

何为函数指针?答案:C Programming Language. 能够查阅下,从原理上来讲,就是一个内存地址。跳过去运行相应的代码段。
既然如此,在运行时决定跳到哪个地方去运行特定的代码就可以。

一个简单的版本号:

以音频解码器作为样例:AAC 解码器,Mpeg解码器。以及其它类型的解码器。

那手动的多态可能会这样实现:
U32 audioHandle = AudioDecOpen(int type)
{
if(type == aac)
return aac_open();
else if(type == mpeg)
return mpeg_open();
}
这种代码不利于扩展,没增加一个新的实例。就得修改AudioDecOpen这个函数。并且封装的不好。

第二种方法来写:

首先定义三种公有函数的函数指针。
typedef int (*OpenFunc) (void *this);
typedef int (*CloseFunc) (void *this);
typedef int (*ControlFunc) (void *this, int command, void *param);

定义公共接口结构体 &
AudioDecoder 对象:
struct module
{ OpenFunc Open; CloseFunc Close; ControlFunc Control;};
struct AudioDecoder{
struct module m;
int audioType;
void* private;
};
提供一个表驱动来方便找到相应的入口:
struct AudioPool{
int audioType;
struct module* audioModule;
}pool[] = {
{aac , aac_module},
{mpeg , mpeg_module},
};

int AudioCreate(int type , Handle *handle)
{
AudioDecoder dec = alloc_audioDec(); foreach(pool , k)
{
if(k->audioType == type)
{
dec->m = k->audioModule;
}
}
*handle = (Handle)dec;
}

这样,当外界去Create一个Audio的对象时,就已经初始化好相应的函数入口了。Open就非常easy了:

int AudioOpen(struct AudioDecoder *dec)
{
return dec->m->Open(dec);
}

当中AudioDecoder中的Private 则是在各自的Open中自己申请,自己释放,Close,Control 相似。

今后维护这个表驱动就可以(pool),新的对象的支持增加进来就可以了,非常方便维护。

更好的维护pool

如今的pool依旧拓展性不太好,毕竟每次增加新的对象都得修改pool这个表驱动。
这里提供一个更好的方法:
struct AudioPool{
int audioType;
struct module* audioModule;
}pool[MAX_POOL];

在提供一个Pool_Register(int type , struct module* module); 的功能:
int Pool_Register(int type , struct module* module);
{
for_each(pool , k)
{
if(k->type == INVALID_AUDIO_TYPE)
{
k->type = type;
k->audioModule = module;
}
} if(k == NULL)
{
return REACH_POOL_END;
}
return NO_ERROR;
}

这样在每一个实例中调用 rigister 就能够非常优雅的解决问题。

附上两个解码器的对象的代码,Mpeg的解码器使用的是 libmad , aac的解码器使用的是 libfaad 库:
AAC代码片段:
.
.
.
static int Close(void *this)
{
AudioSoftDecoder *ad = (AudioSoftDecoder*)this;
if(!ad || !ad->privateData)
{
syslog(LOG_ERR , "%s(%d):Bad Parameter !!!\n" , __FUNCTION__ , __LINE__ );
return CT_ERROR_BAD_PARAMETER;
}
AacFaadPrivate *private = (AacFaadPrivate *)ad->privateData; private->exit = TRUE; if(private->decoderPid > 0)
{
pthread_join(private->decoderPid , NULL);
} if(private->hDecoder)
{
NeAACDecClose(private->hDecoder);
} free(private); ad->privateData = NULL;
return CT_ERROR_NO_ERROR;
} int AAC_Init()
{
return RegisterAudioSoftDec(AudioDecType_AAC ,&aacModule);
}

MPEG代码片段:
.
.
.
int Close(void *this)
{
AudioSoftDecoder *ad = (AudioSoftDecoder*)this;
if(!ad || !ad->privateData)
{
syslog(LOG_ERR , "%s(%d):Bad Parameter !!!\n" , __FUNCTION__ , __LINE__ );
return CT_ERROR_BAD_PARAMETER;
}
mpegMadPrivate *private = (mpegMadPrivate *)ad->privateData; private->exit = TRUE; if(private->decoderPid > 0)
{
pthread_join(private->decoderPid , NULL);
} mad_decoder_finish(&private->decoder); if(private->data.buffer)
{
free(private->data.buffer);
} free(private);
ad->privateData = NULL;
return CT_ERROR_NO_ERROR;
} int Control(void *this , U32 cmd ,void* param)
{
return CT_ERROR_NO_ERROR;
} int MPEG_Init()
{
return RegisterAudioSoftDec(AudioDecType_MPEG ,&mpegModule);
}

总结:

使用面向对象来设计自己的代码。维护上能够降低非常多工作量。

在C语言里面还实现了MVC模式等,这部分也是函数指针实现的。实际上仅仅是一个回调。

可是代码维护,模块划分上,非常清晰。

C 语言实现多态的原理:函数指针的更多相关文章

  1. C语言结构体中的函数指针

      这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in ...

  2. 【嵌入式开发】C语言 结构体相关 的 函数 指针 数组

    . 作者 : 万境绝尘 转载请注明出处 : http://www.hanshuliang.com/?post=30 . 结构体概述 : 结构体是 多个 变量的集合, 变量的类型可以不同; -- 可进行 ...

  3. 复习C语言系列二:动态调用函数指针数组

    a:用call_fun_ptr调用afun(),b:用call_fun_ptr调用bfun() a 请输入给您指定的函数输调用的参数 afun_par ------------------------ ...

  4. C语言复杂的函数指针声明

    复习C语言ING,发现复杂的函数指针声明看不懂,百度半天终于略知一二. 讲的比较详细的一篇blog: http://blog.csdn.net/megaboy/article/details/4827 ...

  5. Day8 函数指针做函数参数

    课堂笔记 课程回顾         多态 virtual关键字 纯虚函数 virtual func() = 0;         提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. ...

  6. C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)

    //多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...

  7. c++语言虚函数实现多态的原理(更新版)

    自上一个帖子之间跳过了一篇总结性的帖子,之后再发,今天主要研究了c++语言当中虚函数对多态的实现,感叹于c++设计者的精妙绝伦 c++中虚函数表的作用主要是实现了多态的机制.首先先解释一下多态的概念, ...

  8. 2014 0416 word清楚项目黑点 输入矩阵 普通继承和虚继承 函数指针实现多态 强弱类型语言

    1.word 如何清除项目黑点 选中文字区域,选择开始->样式->全部清除 2.公式编辑器输入矩阵 先输入方括号,接着选择格式->中间对齐,然后点下面红色框里的东西,组后输入数据   ...

  9. Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针

    Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针   1.1. java方法引用(Method References) 与c#委托与脚本语言js ...

随机推荐

  1. PHP学习4——面向对象

    主要内容: 创建类 成员方法 构造方法 析构方法 封装 继承 接口 多态 静态成员 常用关键字 常用魔术方法 从PHP5开始引入了面向对象的全部机制,面向对象的特性符合软件工程的3个目标:重用性,灵活 ...

  2. ASP.NET 4.5.256 尚未在Web服务器上注册。

    最近在网上下载的一个原型用VS2012打开报错如下: 解决方法: 打开网址:http://blogs.msdn.com/b/webdev/archive/2014/11/11/dialog-box-m ...

  3. 用c+libcurl+PCRE写爬虫2--好用的正则表达式

    写爬虫最重要的就是正则表达式的处理(爬出来的数据的筛选,清洗,过滤等操作). 通过一篇文章 http://blog.csdn.net/quaful/article/details/6460880 来确 ...

  4. 解决javac无效的目标发行版1.8问题

    之前遇到了几次这个问题,解决了又忘记了,所以特别记录一下这个问题. 遇到这个问题,改pom文件不行,改project的sdk也不行,后面看到网上说真正的原因是maven的runner的jre的环境依然 ...

  5. 一、python简单爬取静态网页

    一.简单爬虫框架 简单爬虫框架由四个部分组成:URL管理器.网页下载器.网页解析器.调度器,还有应用这一部分,应用主要是NLP配合相关业务. 它的基本逻辑是这样的:给定一个要访问的URL,获取这个ht ...

  6. vsphere client 创建虚拟机 如何关联到本地iso文件

    问题:以前用过vmere 创建虚拟机,都要在虚拟机启动之前配置系统镜像文件,第一次使用vspere client时在创建虚拟机后,我就想着应该先配置,再启动,其实,非也,应该这样,先启动虚拟机,在点按 ...

  7. 微信小程序,动态改变样式

    小程序目前没有修改样式api,但是可以利用数据绑定实现动态改变样式,可以用view标签模拟page然后改变view标签的样式,以下案例演示了如果改变page背景颜色: <view class=& ...

  8. CentOS 编译 openjdk

    1. 概述 <<深入理解Java虚拟机--JVM高级特性与最佳实践>>第一章就谈到自己编译jdk,来吧. 2.  编译环境 VMware12 CentOS-7-x86_64-E ...

  9. Web前端面试指导(二十):JavaScript中如何翻转一个字符串?

    题目点评 字符串作在程序中是非常常见的,因为程序中绝大部分的数据都可以当作字符串来处理.需要对字符的处理方法比较熟悉,在回答的时候尽量能够说出多种解决方法更好! 字符串翻转的方法 1)使用字符串函数 ...

  10. js截取关键字之后的字符串

    需求:截取下面字符串"="之后的所有字符 var str = "12345=6"; //要截取的字符串 var index = str.indexOf(&quo ...