龙空技术网

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

C语言编程大课堂 418

前言:

如今姐妹们对“c语言求原理”可能比较看重,小伙伴们都需要剖析一些“c语言求原理”的相关资讯。那么小编也在网络上网罗了一些关于“c语言求原理””的相关知识,希望各位老铁们能喜欢,各位老铁们一起来学习一下吧!

何为函数指针?

从原理上来讲,就是一个内存地址,跳过去执行对应的代码段。既然如此,在运行时决定跳到哪个地方去执行特定的代码即可。

以音频解码器作为例子: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;

};

想要学习更多C/C++编程知识,可以加入C/C++学习交流群:587250700和大家一起交流学习。

提供一个表驱动来方便找到对应的入口:

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就非常简单了:

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;

}

想要学习更多C/C++编程知识,可以加入C/C++学习交流群:587250700和大家一起交流学习。

这样在每个实例中调用 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/C++编程知识,可以加入C/C++学习交流群:587250700和大家一起交流学习。

标签: #c语言求原理