c 面向对象程序语言,用 C 语言实现面向对象编程

一、类的封装实现:借用高焕堂的宏头文件,类很容易封装为如下的格式

1、类的定义,其中 CLASS() 是 lw_oopc_kc.h 中定义的宏

#include "lw_oopc_kc.h"

CLASS(A)

{

int a; void(*init)(void*,int); void(*put)(void*);

};

2、成员函数的实现

类的封装实质是用借用 struct 结构体,用函数指针来表示 C++中类的方法(成员函数)。接下来给类

A 的方法写实体函数。

void init_A(void *t,int x)

{

A *cthis = (A*)t;

cthis->a = x;

}

void put_A(void*t)

{

A *cthis = (A*)t;

printf(" %d ",cthis->a);

}

3、类(结构体)中的函数指针与实现函数的关联 通过下面的宏把类的方法(函数指针)和实现函数关联:

CTOR(A)

FUNCTION_SETTING (init, init_A); FUNCTION_SETTING (put, put_A);

END_CTOR

4、对象的定义、构造和初始化

如果没有这个连接处理,类(实际是 struct)中的函数指针就没有函数的功能。函数 init_A()是

XXX_A() 的命名模式,是指明 XXX_A()属于 A 类的函数,方便程序的理解和维护。下面就是要构造

类。在 C++中这个工作系统自动调用构造函数实现而在 C 中,这个过程智能显示调用来实现。借助 lw_oopc_kc.h

(或"lw_oopc.h")可以利用宏CLASS_CTOR(class,obj)来将定义的对象进行构造,使之

有数据的同时有方法的功能。实例化一个对象 3 步子如下:

A aa1; // 1、定义对象

CLASS_CTOR(A,aa1); // 2、构造对象—使得函数指针和函数关联

aa1.init(&aa1, 10); // 3、初始化对象的成员变量,注意要: &aa1(取地址)

二、C 继承的实现:

1、子类的定义:在类的开头借用已经定义的类进行定义一个变量,为了更加明白,表明是继承,增加一个宏定义:

CLASS(B)

{

INHERIT(A); // 继承 A 类 int b; // 子类的成员 void (*init) (void*, int x);

void (*put) (void*);

};

于是以类 B 继承类 A 为例子如下:

void init_B (void*t, int x, int y)

{

B *cthis = (B*) t;

CLASS_CTOR(A, cthis->A); //----继承的基类在这里构造,对象是 cthis->A cthis->A.init(&cthis->A, x);

//----继承的基类的初始化, 注意:&cthis->A cthis->b = y;

}

void put_B (void *t)

{

B *cthis = (B*) t;

cthis->A.put (&cthis->A); //---子类调用父类的方式

printf(" %d ",cthis->b); //---输出类成员值

}

2、子类的成员函数实现,为了方便辨别,类 B 的成员函数带后缀 ‘_B’

int main()

{

A aa1; B b;

CLASS_CTOR(A,aa1); //--构造 aa1 对象 aa1.init(&aa1,5);

//--初始化 aa1 对象aa1.put(&aa1);

//--调用 aa1 对象的成员函数

CLASS_CTOR(B, b); //---构造 b 对象

b.init(&b,100,78); //--初始化 b 对象,包括基类 A 的构造和初始化

b.put(&b); //--调用 b 对象成员函数

b.A.put(&b.A); //--调用 b 对象的基类成员函数

return 0;

3、子类的构造函数,和无继承类一样,将函数指针和函数关联

CTOR(B)

FUNCTION_SETTING (init, init_B); //---函数指针和函数关联的宏

FUNCTION_SETTING (put, put_B); END_CTOR

说明:对基类的构造,不能在子类的构造宏 CTOR(B) 和 END_CTOR 之间进行,因为那时候子类

B 没有实例化,故没有实体对象,CLASS_CTOR(A, cthis->A);不能放在里面,只好放在

init_B() 函数里面,因为那时候 B 类已经有实例化对象了。这样的做法与 C++的做法不一样。C++在构造

B 的对象时,先调用 A 类的构造函数实例化对象中的基类部分。下面为main()函数的调用处理:

int main()

{

A aa1; B b;

CLASS_CTOR(A,aa1); //--构造 aa1 对象 aa1.init(&aa1,5);

//--初始化 aa1 对象aa1.put(&aa1);

//--调用 aa1 对象的成员函数

CLASS_CTOR(B, b); //---构造 b 对象

b.init(&b,100,78); //--初始化 b 对象,包括基类 A 的构造和初始化

b.put(&b); //--调用 b 对象成员函数

b.A.put(&b.A); //--调用 b 对象的基类成员函数

return 0;

输出结果为:5 100 78 100

三、多态的实现:

多态,简而言之即一个接口,多种实现。也就是用相同的抽象类的代码实现不同 的功能。在 C 中多态的实现是通过接口来实现的。借用

lw_oopc.h 宏文件,设计一个计算的多态例子如下:

1、接口的定义:本例是实现加法、减法运算。

加和减都是调用类的同一个成员函数,却分别实现 了加、减的功能。本例的接口表示获得计算结果,但不知道采样什么样的计算方法。

/* operater.h */

#ifndef OPER_H

#define OPER_H INTERFACE(IOPERATOR)

{

double (*GetResult)(double,double);

};

#endif

/*-------------end of operater.h ------------------*/

2、 在加法类 Add 中实现接口 IOPERATOR

/***** Add.C ***/

#include "lw_oopc_kc.h"

#include"operater.h" // 头文件顺序很重要,lw_oopc_kc.h 在前,原因很简单不解释

#include "classes.h"

/************************** 类 Add 定义在 classes.h 中

CLASS(Add)

{

IMPLEMENTS(IOPERATOR);

};************/

static double GetResult(double a,double b)

{

return (a+b);

}

CTOR(Add)

FUNCTION_SETTING(IOPERATOR.GetResult,GetResult); END_CTOR

/***----- END OF ADD.C-----****/

3、 在减法类 Sub 中实现接口 IOPERATOR

/***--- Sub.c ---******/

#include "lw_oopc_kc.h"

#include"operater.h"

#include "classes.h"

/***********类 Sub 定义在 classes.h 中

CLASS(Sub)

{

IMPLEMENTS(IOPERATOR);

};*/

static double GetResult(double a,double b)

{

return (a-b);

}

CTOR(Sub) FUNCTION_SETTING(IOPERATOR.GetResult,GetResult);

END_CTOR

/***----- END OF Sub.C-----****/

4、 组合,把 operater.h、Add.C、Sub.C 和 main.C 组成一个工程,main.c

文件如下:

/***--- main.c ---******/

#include

#include "lw_oopc_kc.h"

#include"operater.h" // 头文件顺序很讲究,lw_oopc_kc.h 必须在前面

#include "classes.h" int main()

{

int a = 10, b=5;

int c1,c2;

IOPERATOR *poper; //--定义接口指针,用指针实现多态

Add A; //---对象 A 成员函数实现加法

Sub S; //---对象 B 成员函数实现减法

CLASS_CTOR(Add, A); CLASS_CTOR(Sub, S);

//---静态内存处理方法

poper = &A; //也可以动态内存方法:oper = New(Add); 记得 free()

c1 = (poper->GetResult(a,b)); // c1 的结果 = 15 ( a+b)

poper = &S;

c2 = poper->GetResult(a,b); // c2 结果= 5 (a-b)

return 0;

}

/***----- END OF main.C-----****/

总结:

1、在 lw_oopc_kc.h 的基础上,为了增加可理解性,不改变原作含义为前提下,增加了以下宏

#define CLASS_CTOR(Class,obj) Class##Setting(&obj) //--对象的构造宏

#define INHERIT(BASE) IMPLEMENTS(BASE) //---类继承宏

#ifndef LW_OOPC_PURE_STATIC

#ifndef LW_OOPC_STATIC

#define New(Class) Class##New() //--对象动态构造宏

#endif

#endif

2、类的实例化必须有 3 步:

定义、构造、初始化。尤其初始化时候通常是通过指针的应用来实现对类内部成员的访问。

3、继承实现方法:

用父类名在子类中定义一个对象作为子类的一个成员变量,通过拥有该对象实 现子类对父类功能的拥有,即继承。

4、注意:子类成员中用父类定义的对象,其构造函数要放在子类的初始化函数里(本人的解决方

法),因为子类的构造函数通过宏实现,不能直接调用父类的构造函数(如果您有更好办法,请和给大家分享)。

5、 函数和函数指针的写法:将函数名变为指针,函数参数只要参数说明。

e.g. double GetResult(double a,double b) 转为函数指针为:

附:lw_oopc_kc.h 宏文件内容

/* lw_oopc_kc.h */

#ifndef _LW_OOPC_H

#define _LW_OOPC_H

#include

#define CLASS(type) \ typedef struct type type; \ struct type

#ifndef LW_OOPC_PURE_STATIC

#ifndef LW_OOPC_STATIC

#ifndef LW_OOPC_DYNAMIC

#define CTOR(type) \

void* type##Setting(type*); \

void* type##New()\

{ \

struct type *t; \

t = (struct type *)malloc(sizeof(struct type)); \

return type##Setting(t); \

} \

void* type##Setting(type *t) \

{

#else

#define CTOR(type) \

void* type##New()\

{ \

struct type *t; \

t = (struct type *)malloc(sizeof(struct type));

#endif

#else

#define CTOR(type) \

void* type##Setting(type *t) \

{

#endif

#endif

#define END_CTOR return (void*)t; }

#define FUNCTION_SETTING(f1, f2) t->f1 = f2;

#define IMPLEMENTS(type) type type

#define INTERFACE(type) \ typedef struct type type; \ struct type

#endif

/* end */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值