/*==============hero.c=====================*/
/*这是一个C语言实现继承和重写方法的例子
*继承的实现很简单,只要在子类的结构全里包含父类结构体的成员即可
*函数重写则是通过函数指针实现的,父类和子类在初始化进都把自己相应的函数赋值给一个函数指针,
*调用函数时我们都调用这个函数指针,这样就实现了重写,所以,所谓重写,就是给一个函数指针赋值的过程
*/
#include "string.h"
#include <stdio.h>
typedef enum
{
POWER,//力量型英雄
AGILITY,//敏捷型英雄
WISDOM//智力型英雄
}HeroType;
#define HERO_MEMBER\
int* virtual_table;/*虚表的指针,这就是传说中的虚表*/\
char name[32];/*英雄名称*/\
HeroType type;/*英雄类型*/\
int level;/*等级*/\
int blood;/*血量*/\
int attack;/*攻击力*/\
typedef struct
{
HERO_MEMBER//定义成员变量,把成员变量声明为一个宏,主要是为了方便继承
}Hero;//所有英雄的父类
//下面是hero的成员方法,this在C语言中不是关键字,所以我们可以用this做为形参的名称
void HeroInit(Hero* this,char *name,HeroType type,int level,int blood,int attack);
void HeroIntroduceDefault(Hero *this);
//虚函数调用
typedef void (*HeroIntroduceFun)(Hero *this);//函数指针
#define HeroIntroduce(pHero) ((HeroIntroduceFun)(pHero->virtual_table[0]))(pHero);//调用虚函数,从虚表中取得函数地址,强制转换成相应的函数指针,再调用
int HERO_VIRTUAL_TABLE[]={(int)HeroIntroduceDefault};//HERO的虚表,只有一个虚函数,把所有的虚函数集合在一个表是为了省内存
//初始化,类似于构靠函数
void HeroInit(Hero* this,char *name,HeroType type,int level,int blood,int attack)
{
this->virtual_table=HERO_VIRTUAL_TABLE;//这句是重点
strcpy(this->name,name);
this->type=type;
this->level=level;
this->blood=blood;
this->attack=attack;
}
//默认的介绍自己的方法
void HeroIntroduceDefault(Hero *this)
{
char *type_str[]={"力量","敏捷","智力"};
printf("我是%s,我的基本信息是:\n",this->name);
printf("类型:\t%s\n",type_str[this->type]);
printf("等级:\t%d\n",this->level);
printf("血量:\t%d\n",this->blood);
printf("攻击力:\t%d\n",this->attack);
}
typedef struct
{
HERO_MEMBER/*斧王继承于Hero,所以要包含Hero的成员变量*/\
int helic;/*斧王反击螺旋的等级*/
}FuWang;//斧王
//正面是斧王的成员方法
void FuWangInit(FuWang *this,int helic);
void FuWangIntroduce(FuWang *this);
void FuWangInit(FuWang *this,int helic)
{
HeroInit((Hero*)this,"斧王",POWER,1,450,100);//调用父类的构造方法,初始化自己
this->helic=helic;
this->virtual_table[0]=(int)FuWangIntroduce;//这个是重点,这样就实现了重写
}
void FuWangIntroduce(FuWang *this)
{
HeroIntroduceDefault((Hero*)this);//先调用父类的方法
printf("除此之外,我在被攻击的时候我能自动用螺旋进行反击:\n");
printf("反击螺旋等级:\t%d\n",this->helic);
}
typedef struct
{
HERO_MEMBER/*蓝胖子继承于Hero,所以要包含Hero的成员变量*/\
int explode;/*蓝胖子反击螺旋的等级*/
}LanPangZi;//蓝胖子
//正面是蓝胖子的成员方法
void LanPangZiInit(LanPangZi *this,int helic);
void LanPangZiIntroduce(LanPangZi *this);
void LanPangZiInit(LanPangZi *this,int explode)
{
HeroInit((Hero*)this,"蓝胖子",WISDOM,2,400,90);//调用父类的构造方法,初始化自己
this->explode=explode;
this->virtual_table[0]=(int)LanPangZiIntroduce;//这个是重点,这样就实现了重写
}
void LanPangZiIntroduce(LanPangZi *this)
{
HeroIntroduceDefault((Hero*)this);//先调用父类的方法
printf("除此之外,我能爆人:\n");
printf("爆人等级:\t%d\n",this->explode);
}
int main(int argv,char*argc[])
{
FuWang fw;
LanPangZi lpz;
Hero *hero;
FuWangInit(&fw,1);//调用斧王构造函数,初始化斧王
LanPangZiInit(&lpz,2);//调用蓝胖子构造函数,初始化蓝胖子
hero=(Hero*)&fw;//父类指针引用子类对象
HeroIntroduce(hero);//神奇的多态要发生了
printf("\n");
hero=(Hero*)&lpz;//父类指针引用子类对象
HeroIntroduce(hero);//神奇的多态又发生了
getchar();
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: