C语言实现C++多态------函数指针
2016-10-04 16:24
323 查看
序:
前段时间,去复试淘米的面试,被问到了怎么用C语言实现C++中的多态,当时,只是模模糊糊的知道,使用函数指针可以达到C++多态的效果,但是,具体怎么实现,却还是不清楚。最终面试官让我说了一下C++中的多态。虽然知道被挂在了二面,但是,却感觉并没有什么,每一次的失败,都是为了最后一次的成功积蓄力量,回报越晚,回报越大。这不,因为这件事情,我知道了怎么用C语言实现C++的多态。
正文:
1.首先,弄清楚一个问题,C++多态。
(注:摘自C和C++程序员面试秘笈)
多态:同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。有两种类型的多态性:
<1>编译时的多态性:编译时的多态性是通过重载函数来实现的。对于非虚的成员函数来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
<2>运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C++中,运行时的多态性通过虚成员实现。
示例:
2.C语言实现C++中的多态
(摘自:http://blog.csdn.net/dai_jing/article/details/38232641)
<5>程序运行结果截图:
3.感悟
实际上,在C语言中,模仿C++实现多态的过程中,对于构造和析构函数都是要显示的进行调用,对于类的成员函数,实际上是通过结构体内部封装的函数指针完成的。而对于从基类继承而来的派生类,它的虚表的确定,实际上是在自身的构造函数中显示的调用基类的构造函数,然后复制基类的构造函数的内容,之后,可以在自己的类中添加一些其他的操作,而对于自己本身的函数成员,在本模块内有效,声明为静态函数,这样就可以避免命名的冲突问题。总之,在C语言中要想实现多态,函数指针是唯一法宝。
前段时间,去复试淘米的面试,被问到了怎么用C语言实现C++中的多态,当时,只是模模糊糊的知道,使用函数指针可以达到C++多态的效果,但是,具体怎么实现,却还是不清楚。最终面试官让我说了一下C++中的多态。虽然知道被挂在了二面,但是,却感觉并没有什么,每一次的失败,都是为了最后一次的成功积蓄力量,回报越晚,回报越大。这不,因为这件事情,我知道了怎么用C语言实现C++的多态。
正文:
1.首先,弄清楚一个问题,C++多态。
(注:摘自C和C++程序员面试秘笈)
多态:同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。有两种类型的多态性:
<1>编译时的多态性:编译时的多态性是通过重载函数来实现的。对于非虚的成员函数来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
<2>运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C++中,运行时的多态性通过虚成员实现。
示例:
这里写代码片 #include <iostream> using namespace std; class A { public: virtual void f() { cout << "A::f()" << endl; } }; class B:public A { public: virtual void f() { cout << "B::f()" << endl; } }; class C:public B { public: void f() { cout << "C::f()" << endl; } }; void test(A &a) //基类的指针或引用 { a.f(); //运行时多态 } int main() { A a; B b; C c; test(a); test(b); test(c); return 0; }
2.C语言实现C++中的多态
(摘自:http://blog.csdn.net/dai_jing/article/details/38232641)
这里写代码片 <1>基类头文件 #ifndef _ANIMAL_H_ #define _ANIMAL_H_ //动物的行为 typedef struct animal_ops_s_ { void (*eat)(char *food); //吃什么食物 void (*walk)(int steps); //走多少步 void (*talk)(char *msg); //说什么 }animal_ops_t; //动物类,所有动物的基类(抽象类) typedef struct animal_s_ { char *name; //动物的名称 animal_ops_t *animal_ops; //动物的行为 }animal_t; //基类的构造函数,需要显示调用 extern animal_t *animal_init(char *name); //基类的相关操作 extern void animal_eat(animal_t *animal,char *food); extern void animal_walk(animal_t *animal,int steps); extern void animal_talk(animal_t *animal,char *msg); //基类的析构函数,需要显示调用 extern void animal_die(animal_t *animal); #endif <1>基类的实现 #include <assert.h> #include <stdlib.h> #include <string.h> #include "animal.h" //基类的构造函数,需要显示调用 animal_t *animal_init(char *name) { assert(name != NULL); size_t name_len = strlen(name); animal_t *animal = (animal_t *)malloc(sizeof(animal_t)); memset(animal,0,sizeof(animal)); animal->name = (char *)malloc(name_len + 1); memcpy(animal->name,name,name_len+1); animal->animal_ops = (animal_ops_t *)((char *)animal+name_len + 1); animal->animal_ops->eat = NULL; animal->animal_ops->walk = NULL; animal->animal_ops->talk = NULL; return animal; } //基类相关的操作 void animal_eat(animal_t *animal,char *food) { animal->animal_ops->eat(food); } void animal_walk(animal_t *animal,int steps) { animal->animal_ops->walk(steps); } void animal_talk(animal_t *animal,char *msg) { animal->animal_ops->talk(msg); } //基类的析构函数,需要显示调用 void animal_die(animal_t *animal) { return ; } <2>汪星人头文件 #ifndef _DOG_H_ #define _DOG_H_ #include "animal.h" typedef struct dog_s_ dog_t; struct dog_s_ { animal_t base; //继承自animal基类 }; extern dog_t *dog_init(); extern void dog_die(dog_t *dog); #endif <2>汪星人实现 #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "dog.h" static void eat(char *food); static void walk(int steps); static void talk(char *msg); dog_t *dog_init() { dog_t *dog = (dog_t *)malloc(sizeof(dog_t)); animal_t *animal = (animal_t *)animal_init("hello-dog"); memcpy(&(dog->base),animal,sizeof(animal_t)); dog->base.animal_ops->eat = eat; dog->base.animal_ops->walk = walk; dog->base.animal_ops->talk = talk; animal_die(animal); return dog; } void dog_die(dog_t *dog) { assert(dog != NULL); free(dog); dog = NULL; } static void eat(char *food) { printf("I'm a dog,I eat %s\n",food); } static void walk(int steps) { printf("I'm a dog, I can jump %d steps\n",steps); } static void talk(char *msg) { printf("I'm a dog,I talk my language %s\n",msg); } <3>喵星人头文件 #ifndef _CAT_H_ #define _CAT_H_ #include "animal.h" typedef struct cat_s_ cat_t; struct cat_s_ { animal_t base; //继承自animal基类 }; extern cat_t *cat_init(); extern void cat_die(cat_t *cat); #endif <3>喵星人实现 #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "cat.h" static void eat(char *food); static void walk(int steps); static void talk(char *msg); cat_t *cat_init() { cat_t *cat = (cat_t *)malloc(sizeof(cat_t)); animal_t *animal = (animal_t*)animal_init("hello-cat"); memcpy(&(cat->base),animal,sizeof(animal_t)); cat->base.animal_ops->eat = eat; cat->base.animal_ops->walk = walk; cat->base.animal_ops->talk = talk; return cat; } void cat_die(cat_t *cat) { assert(cat != NULL); free(cat); cat = NULL; } static void eat(char *food) { printf("I'm a cat,I eat %s\n",food); } static void walk(int steps) { printf("I'm a cat,I can jump %d steps\n",steps); } static void talk(char *msg) { printf("I'm a cat,I talk my language %s\n",msg); } <4>主函数 #include <stdio.h> #include "animal.h" #include "dog.h" #include "cat.h" int main() { cat_t *cat = cat_init(); dog_t *dog = dog_init(); //dog测试 animal_eat(dog,"bones"); animal_walk(dog,5); animal_talk(dog,"wang wang wang..."); //cat测试 animal_eat(cat,"fish"); animal_walk(cat,3); animal_talk(cat,"miao miao miao..."); cat_die(cat); dog_die(dog); return 0; }
<5>程序运行结果截图:
3.感悟
实际上,在C语言中,模仿C++实现多态的过程中,对于构造和析构函数都是要显示的进行调用,对于类的成员函数,实际上是通过结构体内部封装的函数指针完成的。而对于从基类继承而来的派生类,它的虚表的确定,实际上是在自身的构造函数中显示的调用基类的构造函数,然后复制基类的构造函数的内容,之后,可以在自己的类中添加一些其他的操作,而对于自己本身的函数成员,在本模块内有效,声明为静态函数,这样就可以避免命名的冲突问题。总之,在C语言中要想实现多态,函数指针是唯一法宝。
相关文章推荐
- C语言实现C++的继承和多态
- C语言模拟实现C++的继承与多态
- C语言实现C++的封装继承与多态
- C语言模式实现C++继承和多态
- C语言如何模拟C++实现继承和多态
- 如何用C语言实现类似C++中的多态
- C语言模式实现C++继承和多态
- C语言实现C++继承和多态的代码分享
- 模拟继承和多态--C语言模式实现C++继承和多态
- c语言模拟实现c++的继承多态
- C语言实现C++的封装继承和多态
- C语言模式实现C++继承和多态
- 用C语言实现c++的封装、继承、多态
- C语言模式实现C++继承和多态
- 如何用C语言实现C++的基本特性:封装、继承、多态
- C语言实现C++面向对象语言多态特性
- C语言模拟实现C++中的继承和多态
- C语言模拟实现C++的继承与多态
- C语言模拟实现C++中的继承和多态
- C语言模拟实现C++的继承多态