分类:
2008-10-13 16:09:56
今天论坛上有人在问,如何用c 实现c++的继承, 我告诉他是结构加指针实现,虽然表达简单,但的确需要这两样东西,
另外感觉继承主要好处就是实现多态性,那用c实现了多态性,估计也就用到了继承的优点
以前是在vc编程难点剖析一书里看到过用c实现多态性的的方法,说到这本书还是要表扬一下的,vc编程难点剖析这本书写得很不错的,那时在新风雨,打5折买的,看来好东西,不一定价高,那本书的源码很简单,如下:
#include "stdio.h"
#include "stdlib.h"
//定义函数指针类型DISPLAYINTEGER,指向返回值为void,参数列表为(const int)的函数
typedef void( *DISPLAYINTEGER)(const int);
//定义函数,将数字以十进制形式输出,该函数类型与DISPLAYINTEGER匹配
void DisplayDecimal(const int Number)
{
printf("The decimal value is %d\n",Number);
}
//定义函数,将数字以八进制形式输出,该函数类型与DISPLAYINTEGER匹配
void DisplayOctal(const int Number)
{
printf("The octal value is %o\n",Number);
}
//定义函数,将数字以十六进制形式输出,该函数类型与DISPLAYINTEGER匹配
void DisplayHexadecimal (const int Number)
{
printf("The hexadecimal value is %x\n",Number);
}
/********************************************************************
定义通用的显示数字函数
DisplayFormat DISPLAYINTEGER函数指针类型,实参可以是以上定义的
三个函数之一。通过传递不同的实参,将数字以各种格式输出。
Number 准备输出的数字
********************************************************************/
void DisplayNumber(DISPLAYINTEGER DisplayFormat,const int Number)
{
//调用以实参传入的函数,以某种格式输出整型数字
DisplayFormat(Number);
}
int main(int argc, char* argv[])
{
int Number=0;
// 如果有数字形式的命令行参数,将其输出,否则输出0
if(argc>1)
Number=atoi(argv[1]);
//分别以三种格式将数字输出
DisplayNumber(DisplayDecimal,Number);
DisplayNumber(DisplayOctal,Number);
DisplayNumber(DisplayHexadecimal,Number);
return 0;
}
看起来通俗易懂,不过没有继承 的感觉
以前还在其他地方看到过类似c 实现继承的代码
下午我就简化了一段代码,并且编译执行了下,来实现c 的所谓继承,代码如下:
1.parent.h
#ifndef PARENT_H
#define PARENT_H
#include "child1.h"
#include "child2.h"
struct parent_type{
unsigned int id;
//char classname[20];
char * name;
struct{
struct parent_handle * (*init)(void * pvoid);
int (*fp1)(struct parent_handle *ph);
//...
}pfn;
struct parent_type *next;
};
struct parent_handle{
int i;
union{
struct child1_handle child_hdl1;
struct child2_handle child_hdl2;
//...
}priv;
struct parent_type *ptp;
};
2.parent.h
#include "stdafx.h"
#include "parent.h"
static struct parent_type *class_list;
int register_child(struct parent_type *p)
{
p->next = class_list;
class_list = p;
return 0;
}
struct parent_handle * parent_init(void * pchild_priv, unsigned int id)
{
struct parent_type *p;
for (p = class_list; p; p = p->next)
if (p->id == id)
return p->pfn.init(pchild_priv);
printf("unable to find matching child class\n");
return NULL;
}
int parent_fp1(struct parent_handle *ph)
{
if (!ph->ptp->pfn.fp1)
return 0;
return ph->ptp->pfn.fp1(ph);
}
int register_child(struct parent_type *p);
struct parent_handle * parent_init(void * pchild_priv, unsigned int id);
int parent_fp1(struct parent_handle *ph);
#endif
3. child1.h
#ifndef CHILD1_H
#define CHILD1_H
#define CHILD_1_ID 101
struct child1_handle
{
char child1_decr[20];
int child1_data;
//...
};
extern struct parent_type child_tp1;
struct parent_handle * child1_init(void * pvoid);
int child1_fp1(struct parent_handle *ph);
#endif
4.child1.c
#include "stdafx.h"
#include "parent.h"
#include "child1.h"
struct parent_type child_tp1= {CHILD_1_ID,"class child1",{&child1_init,&child1_fp1},0};
/*
struct parent_type child1= {
.id = CHILD_1_ID,
.name = "class child1",
.fn = {
.init = &child1_init,
.fp1 = &child1_fp1,
},
};
*/
struct parent_handle * child1_init(void * pvoid)
{
//int ret;
struct child1_handle *h;
struct parent_handle *ph = (struct parent_handle *)malloc(sizeof(struct parent_handle/* *h */));
if (!ph)
return NULL;
ph->ptp = &child_tp1;
//todo
h = &ph->priv.child_hdl1;
strcpy(h->child1_decr,"hello child1!");
h->child1_data=*((int*)(pvoid));
//...
return ph;
}
int child1_fp1(struct parent_handle *ph)
{
struct child1_handle *h = &ph->priv.child_hdl1;
//todo
printf("%s,data=%d\r\n",h->child1_decr,h->child1_data);
//...
return 0;
}
5.child2.h
#ifndef CHILD2_H
#define CHILD2_H
#define CHILD_2_ID 102
struct child2_handle
{
int child2_data;
char child2_decr[20];
//...
};
extern struct parent_type child_tp2;
int child2_fp1(struct parent_handle *ph);
struct parent_handle * child2_init(void * pvoid);
#endif
6.child2.c
#include "stdafx.h"
#include "parent.h"
#include "child2.h"
struct parent_type child_tp2= {CHILD_2_ID,"class child2",{&child2_init,&child2_fp1},0};
/*
struct parent_type child1= {
.id = CHILD_1_ID,
.name = "class child1",
.fn = {
.init = &child1_init,
.fp1 = &child1_fp1,
},
};
*/
struct parent_handle * child2_init(void * pvoid)
{
//int ret;
struct child2_handle *h;
struct parent_handle *ph = (struct parent_handle *)malloc(sizeof(struct parent_handle/* *h */)); //别忘了自己加deinit 把它释放
if (!ph)
return NULL;
ph->ptp = &child_tp2;
//todo
h = &ph->priv.child_hdl2;
strcpy(h->child2_decr,"hello child2!");
h->child2_data=*((int*)(pvoid));
//...
return ph;
}
int child2_fp1(struct parent_handle *ph)
{
struct child2_handle *h = &ph->priv.child_hdl2;
//todo
printf("%s,data=%d\r\n",h->child2_decr,h->child2_data);
//...
return 0;
}
最后是main.c
// testClass.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "parent.h"
#include "child1.h"
#include "child2.h"
static struct parent_handle *pchild_1_h,*pchild_2_h;
int main(int argc, char* argv[])
{
//printf("Hello World!\n");
int child1_priv=123;
int child2_priv=456;
register_child(&child_tp1); //注册子类1
pchild_1_h = parent_init((void *)(&child1_priv),CHILD_1_ID); //初始化子类1
if(pchild_1_h)
parent_fp1(pchild_1_h); //执行子类1的fp1函数
register_child(&child_tp2); //注册子类2
pchild_2_h = parent_init((void *)(&child2_priv),CHILD_2_ID); //初始化子类2
parent_fp1(pchild_2_h); //执行子类2的fp1函数
return 0;
}
/*
用c++实现很简单
class parent
{
virturl int fp1 ();
}
class child1 :public parent
{
char child1_decr[20];
int child1_data;
int fp1 ();
}
class child2 :public parent
{
char child2_decr[20];
int child2_data;
int fp1 ();
}
parent * pa;
child1 ch1b;
pa= ch1b;
pa->fp1;
*/
用c实现一些类似c++的功能还是有好处的,一方面多重继承开销大,而且在底层编程,c 用得比较多,所以总结了下,以后可能有点用