700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 如何利用函数指针在c语言中实现面向对象编程

如何利用函数指针在c语言中实现面向对象编程

时间:2023-09-21 18:35:48

相关推荐

如何利用函数指针在c语言中实现面向对象编程

面向过程编程

c语言,是一种函数流语言,看他的代码,大部分是call1(data), call2(data)类似的代码。所以他的主体思想是函数,把数据丢进去给函数执行。

面向对象编程

java语言,和c++一脉相承,继承了面向对象的编程思想。 即,

class A {methodA();methodB();}

这种语言表达的主体,是一个对象。不论有什么要执行,首先诞生一个对象A a = new A();,然后调用该对象的方法:a.methodA()

这是两种不同的观点,导致语法,使用方式,还有执行过程的差异。

弥合二者的差异

那么,有没有一种办法,可以弥合这两种观点的差异,实现用c语言表达对象,用c语言的形式像java那样调用方法呢?

有的

结构体

c语言有一种语法:

void turnOff() {printf("light off");}void turnOn() {print("light on");}type define struct Switch Switch;struct Light {int num;void *turnOff();void *turnOn();};

可以这样理解上述代码:

struct Light是一个结构体,结构体可以包含基本变量,指针,但是不能定义函数。函数不能定义在结构体中,但是可以定义一个函数指针。函数指针就可以指向具体的函数。

例如想让灯打开,关闭,我们这样写:

Light *light;// 首先,实例化Lightlight = (Light *) malloc(sizeof(Light));// 接着,让函数指针指向一个函数light->turnOff = turnOff;light->turnOn = turnOn;// 最后,模拟对象调用方法的形式调用函数light->turnOn();light->turnOff();

struct 里函数指针的使用目的

上面讲到函数指针,他的用法已经明白,其实目的也很清楚了,就是实现面向对象的思想,让函数和对象关联,可以从对象(结构体)直接调用关联函数。

函数表(Function Table)的意义,和结构的关系

对于结构体中的函数指针,通常不止一个,可能7,8个,上十个都挺常见的,我们为了reuse, 产生了“函数表”的概念。

struct LightTable {void *turnOn();void *turnOff();}struct Light {int num;struct LightTable table;}

这段代码就是讲,把函数指针独立出来,形成一个结构体,可以单独产生对象,被复用,节省运行内存了。

说了半天,函数表有啥用呢?

jni调用中使用函数表的一个实例:

Android JNIEnv 用到的Function Table

为什么要讲上面的函数指针呢?因为他非常重要,在android源码中被大量用到:

先来看看android 5.0源码中的jni_internal.h文件中有这样一个函数表定义:

static JNINativeMethod gMethods[] = {NATIVE_METHOD(Runtime, freeMemory, "!()J"),NATIVE_METHOD(Runtime, gc, "()V"),NATIVE_METHOD(Runtime, maxMemory, "!()J"),NATIVE_METHOD(Runtime, nativeExit, "(I)V"),NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"),NATIVE_METHOD(Runtime, totalMemory, "!()J"),};

而在源码文件runtime/方法:RegisterNativeMethods是这样实现(删除若干不必要代码):

static jint RegisterNativeMethods(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, jint method_count, bool return_errors) {mirror::Class* c = soa.Decode<mirror::Class*>(java_class);for (jint i = 0; i < method_count; ++i) {const void* fnPtr = methods[i].fnPtr;mirror::ArtMethod* m = c->FindDirectMethod(name, sig);if (m == nullptr) {m = c->FindVirtualMethod(name, sig);}m->RegisterNative(soa.Self(), fnPtr, is_fast);}return JNI_OK;}

我们看m->RegisterNative(soa.Self(), fnPtr, is_fast)这一行,即是把函数指针fnPtr作为参数注册到对象(结构体)m中。

总结

函数指针当做结构体或者对象的属性,在android源码中非常常见,他是一种c语言级别实现面向对象思想的常见技术,所以我们要非常熟练的了解和掌握这种技巧。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。