序:
前段时间,去复试淘米的面试,被问到了怎么用 C 语言实现 C++ 中的多态,当时,只是模模糊糊的知道,使用函数指针可以达到 C++ 多态的效果,但是,具体怎么实现,却还是不清楚。最终面试官让我说了一下 C++ 中的多态。虽然知道被挂在了二面,但是,却感觉并没有什么,每一次的失败,都是为了最后一次的成功积蓄力量,回报越晚,回报越大。这不,因为这件事情,我知道了怎么用 C 语言实现 C++ 的多态。
正文:
1. 首先,弄清楚一个问题,C++ 多态。
(注:摘自 C 和 C++ 程序员面试秘笈)
多态:同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。有两种类型的多态性:
<1> 编译时的多态性:编译时的多态性是通过重载函数来实现的。对于非虚的成员函数来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
<2> 运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C++ 中,运行时的多态性通过虚成员实现。
示例:
- 这里写代码片#include 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++ 中的多态
- 这里写代码片 < 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#include#include#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#include#include#include#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#include#include#include#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#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 语言中要想实现多态,函数指针是唯一法宝。
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: http://www.92to.com/bangong/2017/03-10/18399090.html