#ifndef _51_2_H
#define _51_2_H
typedef void Demo;
typedef void Derived;
Demo* Demo_create(int i,int j);
int Demo_geti(Demo*pthis);
int Demo_getj(Demo*pthis);
int Demo_add(Demo*pthis,int value);
void Demo_free(Demo*pthis); Derived*Derived_create(int i,int j,int k);
int Derived_getk(Derived*pthis);
int Derived_add(Derived*pthis,int value);
#endif
   #include<stdio.h>
#include"51-2.h"
#include<malloc.h>
//定义父子类的虚函数
static int Demo_virtual_add(Demo*pthis,int value);
static int Derived_virtual_add(Derived*pthis,int value);
//2。确定虚函数表的类型,虚函数表的结构体,用来创建虚函数表,存储虚函数地址
//目的是为了实现add函数的多态
struct vtbl{
int(*padd)(Derived*,int);//3。函数指针的定义
};
struct classdemo{
struct vtbl* vptr;//1。定义虚函数表指针,指针的类型
int mi;
int mj;
};
static struct vtbl g_Demo_vtbl = {
Demo_virtual_add
};//4。全局虚函数表变量,static关键字将该变量隐藏在此文件中,外部不能访问
static struct vtbl g_Derived_vtbl = {
Derived_virtual_add
};
struct classderived{
struct classdemo d;
int mk;
};
Demo* Demo_create(int i,int j){
struct classdemo* ret = (struct classdemo*)malloc(sizeof(struct classdem o));//分配空间
if(ret != NULL){
ret->vptr = &g_Demo_vtbl;//5。将虚函数表和具体对象关联起来
ret->mi = i;
ret->mj = j;
}
return ret;
}
int Demo_geti(Demo*pthis){//具体实现函数 强制类型转换
struct classdemo* obj = (struct classdemo*)pthis;
return obj->mi;
}
int Demo_getj(Demo*pthis){
struct classdemo* obj = (struct classdemo*)pthis;
return obj->mj;
}
//6。分析、实现具体的虚函数
static int Demo_virtual_add(Demo*pthis,int value){
struct classdemo* obj = (struct classdemo*)pthis;
return obj->vptr->padd(pthis,value);
}
int Demo_add(Demo*pthis,int value){
struct classdemo* obj = (struct classdemo*)pthis;
return obj->mi + obj->mj + value;
}
void Demo_free(Demo*pthis){
free(pthis);
}
Derived*Derived_create(int i,int j,int k){
struct classderived* ret = (struct classderived*)malloc(sizeof(struct cl assderived));
if(ret != NULL){
ret->d.vptr = &g_Derived_vtbl;//关联到子类的虚函数表上去
ret->d.mi = i;
ret->d.mj = j;
ret->d.mi = i;
ret->d.mj = j;
ret->mk = k;
}
return ret;
}
int derived_getk(Derived* pthis){
struct classderived* obj = (struct classderived*)pthis;
return obj->mk;
}
static int Derived_virtual_add(Derived*pthis,int value){
struct classderived* obj = (struct classderived*)pthis;
return obj->mk + value;
}
int Derived_add(Derived*pthis,int value){
struct classderived* obj = (struct classderived*)pthis;
return obj->d.vptr-> padd(pthis,value);
}
   #include<stdio.h>
#include"51-2.h"
void run(Demo*p,int v){
int r = Demo_add(p,v);
printf("r=%d\n",r);
}
int main(){
Demo* pb = Demo_create(,);
Demo* pd = Derived_create(,,); printf("Demo_add(3)=%d\n",Demo_add(pb,));
printf("Derived_add(3)=%d\n",Derived_add(pd,)); run(pb,);
run(pd,);
Demo_free(pb);
Demo_free(pd);
return ;
}

多态的C语言实现版本的更多相关文章

  1. go语言最新版本 下载地址

    国内官方网站无法打开.放在了百度云中,定期会更新: 链接:http://pan.baidu.com/s/1dD59duh 密码:46ek 备用地址:http://pan.baidu.com/s/1hq ...

  2. 如何在Visual studio中修改所使用C#语言的版本

    有时候,我们需要在Visual studio里修改当前使用的C#语言的版本,具体修改方法如下:在solution explorer中右键工程->选择属性->切换到Build页->点击 ...

  3. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  4. C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) C#各版本新特性 C#版本和.NET版本以及VS版本的对应关系

    C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) 2017年08月06日 11:53:13 阅读数:6705 历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有1 ...

  5. 微软的R语言发行版本MRO及开发工具RTVS

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:微软在收购R语言的开发商后,也独立发行或在自己的产品中集成了R语言,这里就介绍下它们包 ...

  6. C# 语言历史版本特性(C# 1.0到C# 8.0汇总)

    历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有17年的历史,语言本身具有丰富的特性,微软对其更新支持也十分支持.微软将C#提交给标准组织ECMA,C# 5.0目前是ECM ...

  7. MFC多语言程序版本,在不同的windows系统上的使用

    如何使MFC程序界面支持多国语言?这次使用后给自己做一个总结. 我们使用vc6.0的版本来试验 1. 切换到资源视图,右键Dialog->Insert Copy 2. ok后,会出来一个语言的选 ...

  8. Python笔记(三)继承和多态、动态语言

    一.继承 先定义一个A类 class A(object): def fun(self): print "Run A fun()" 在定义一个B类 class B(A): pass ...

  9. C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新)

    历史版本C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有17年的历史,语言本身具有丰富的特性,微软对其更新支持也十分支持.微软将C#提交给标准组织ECMA,C# 5.0目前是ECMA ...

随机推荐

  1. Problem 2232 炉石传说

    Problem 2232 炉石传说 不知道fzu的账号在哪里弄,想要做题的可以到vj上面去做 https://vjudge.net/problem/FZU-2232 #include <iost ...

  2. DRF节流组件

    1.DRF节流组件自定义(限制访问频率)  方式一 自定义类和方法: 和上述的认证组件使用方式一样,定义一个频率组件类,推荐继承BaseThrottle类, 需定义defallow_request(s ...

  3. Django视图函数之FBV与CBV模式

    FBV模式: FBV(function base views) 就是在视图里使用函数处理请求. 一般直接用函数写的都属于是FBV模式. veiws.py from django.shortcuts i ...

  4. 都说变量有七八种,到底谁是 Java 的亲儿子

    网上罗列了很多关于变量的理解,良莠不齐,不知道哪些是对的,哪些是错的,所以笔者就这些博客和自己的理解写出这篇文章,如果有不对的地方,希望读者能够指正,感谢. 变量是我们经常用到的一种,我在刚学 Jav ...

  5. POJ3169

    题目链接:http://poj.org/problem?id=3169 AC思路: spfa算法. 设各牛的位置为x[ ]. 对于感情好的牛,即第2到ML+1行:A B D, 有x[B] - x[A] ...

  6. EventBus/EventQueue 再思考

    EventBus/EventQueue 再思考 Intro 之前写过两篇文章,造轮子系列的 EventBus/EventQueue,回想起来觉得当前的想法有点问题,当时对 EvenStore 可能有点 ...

  7. 解决 appium 当中 uiautomator2 无法启动的问题

    在启动 appium 程序中,有时候会出现 uiautomator2 服务无法启动的错误,appium 的日志截图如下: image.png 错误信息: ActivityManager: Unable ...

  8. NO.2 TI开发环境的搭建 SDK+Code Composer Studio

    首先我们要了解TI嵌入式开发环境 对于TI嵌入式开发,首先我们要下载SDK软件包,其次要准备编译环境Code Composer Studio. 对于SDK的下载,可以在官网浏览http://www.t ...

  9. Android_存储之scoped storage&媒体文件

    Scoped storage 文件存储介绍了内部存储和外部存储相关的内容.因为外部存储容易读写,所以在手机中经常看到很多“乱七八糟”的文件或文件夹,这些就是应用肆意创建的. Android Q(10) ...

  10. Linux显示行号设置

    linux显示行号设置 第一步,打开vim vi ~/.vimrc 第二步,在该文件中加入一行,命令如下: set nu # 显示行号 set nonu # 不显示行号 微信公众号:喵哥解说 公众号介 ...