c语言delete函数使用,C语言也能面向对象(三)——通用的new和delete

本文版权所有,转载请注明出处和作者联系方式。

作者:孙华明

联系方式: wormsun at gmail.com

上篇中实现的lw_new和lw_delete函数只能创建和删除animal类的对象,这当然满足不了我们的需要,那么如何实现通用的lw_new和lw_delete函数,用来创建和删除任何类的对象呢?

考虑新定义一个类car,其属性有车标logo和颜色color:

typedef struct _car car;

struct _car

{

/*private data*/

char logo[256];

int color;

};

成员函数:

char* car_get_logo(car* self);

void car_set_logo(car* self, char* logo);

int car_get_color(car* self);

void car_set_color(car* self, int color);

使用lw_new创建car类对象时,必须知道car类的对象占用内存空间大小和构造函数,以便为对象申请内存空间,并初始化该对象,而使用lw_delete函数删除car类的对象时,就必须知道car类的析构函数,以便先析构该对象,然后再释放对象占用的内存空间。可以看出,创建和删除car类的对象所需要的三个必备条件就是:类的对象占用内存空间大小,构造函数和析构函数,与创建和删除animal类时所需的条件一致。那么我们是不是可以创建一个统一的类信息结构体,然后使用结构体的不同对象,保存不同类的类信息呢?

上篇中定义的animal类的类信息结构体如下:

struct _animal_klass_info

{

animal_klass_info* super; /*animal's super's klass info*/

char* name; /*animal klass's name*/

size_t size; /*animal's size*/

animal* (*ctor)(animal* self); /*constructor*/

animal* (*dtor)(animal* self); /*destructor*/

};

super为父类的类信息地址,无父类,则其值为NULL,name是该类的名称,这两个成员先不考虑,我们着重考虑size、ctor和dtor这三个成员,看看是否能够将这个animal专用的类信息结构体,改造成统一的类信息结构体。size为类对象所占内存空间大小,类型为size_t,这对任何类都是通用的,所以无需变更。ctor和dtor都是函数指针类型,传入参数为animal对象的地址,在将animal对象初始化或析构后,再将该地址返回。既然要适用于任意类,在类信息结构体中就不能使用animal类的指针了,我们将结构体中这两个函数的参数和返回值类型弱化为void*类型,如下:

typedef void* (*voidf)(void*);

voidf ctor;

voidf dtor;

注意修改的只是类信息结构体中的函数类型,在实现animal类的构造函数和析构函数时,仍然可以直接使用animal类的指针类型,这样在初始化类信息时,编译器会警告类型不兼容,为了避免警告,我们将类信息结构体中的构造函数和析构函数指针弱化为void*类型,最终类信息结构体的定义为:

typedef struct _klass_info klass_info;

struct _klass_info

{

klass_info* super; /*object's klass's super klass*/

char* name; /*object's klass's name*/

size_t size; /*object's size*/

void* ctor; /*object's constructor*/

void* dtor; /*object's destructor*/

};

lw_new和lw_delete函数的实现也要响应修改,如下:

void* lw_new(void* klass)

{

klass_info* kls = KLASS(klass);

void* p = malloc(kls->size);

*((klass_info**)p) = kls;

return ((voidf)(kls->ctor))(p);

}

void lw_delete(void* self)

{

if(self)

{

klass_info* kls = *((klass_info**)self);

free(((voidf)(kls->dtor))(self));

}

}

为了避免警告,lw_new和lw_delete函数的传入参数类型也弱化为void*类型。klass_info* kls = KLASS(klass)中使用了KLASS()宏,定义如下:

#define KLASS(_klass_info_) ((klass_info*)_klass_info_)

用来将其他指针强制转换为klass_info*类型。

我们以car类为例,看看如何使用klass_info类信息结构体定义类。

car.h

extern klass_info* car_klass;

#define CAR(_object_) ((car*)_object_)

typedef struct _car car;

struct _car

{

/*class info*/

klass_info* klass;

/*private data*/

char logo[256];

int color;

};

char* car_get_logo(car* self);

void car_set_logo(car* self, char* logo);

int car_get_color(car* self);

void car_set_color(car* self, int color);

car.c

#include "car.h"

static car* car_ctor(car* self);

static car* car_dtor(car* self);

static klass_info local_car_klass =

{

NULL,

"car_klass",

sizeof(car),

car_ctor,

car_dtor,

};

klass_info* car_klass = &local_car_klass;

static car* car_ctor(car* self)

{

memset(self->logo, 0x00, sizeof(self->logo));

self->color = 0;

}

static car* car_dtor(car* self)

{

return self;

}

char* car_get_logo(car* self)

{

return self->logo;

}

void car_set_logo(car* self, char* logo)

{

strncpy(self->logo, logo, sizeof(self->logo));

}

int car_get_color(car* self)

{

return self->color;

}

void car_set_color(car* self, int color)

{

self->color = color;

}

下面测试一下:

int main(int argc, char* argv)

{

argc;

argv;

animal* animal1 = NULL;

animal* animal2 = NULL;

car* car1 = NULL;

car* car2 = NULL;

animal1 = lw_new(animal_klass);

animal_set_name(animal1, "Kitty");

animal_set_weight(animal1, 30);

printf("animal1, name : %s, weight : %d/n",

animal_get_name(animal1),

animal_get_weight(animal1));

lw_delete(animal1);

animal2 = lw_new(animal_klass);

animal_set_name(animal2, "Bib");

animal_set_weight(animal2, 10);

printf("animal2, name : %s, weight : %d/n",

animal_get_name(animal2),

animal_get_weight(animal2));

lw_delete(animal2);

car1 = lw_new(car_klass);

car_set_logo(car1, "Honda");

car_set_color(car1, 0);

printf("car1, logo : %s, color : %d/n",

car_get_logo(car1),

car_get_color(car1));

lw_delete(car1);

car2 = lw_new(car_klass);

car_set_logo(car2, "BMW");

car_set_color(car2, 1);

printf("car2, logo : %s, color : %d/n",

car_get_logo(car2),

car_get_color(car2));

lw_delete(car2);

return 0;

}

到这里我们已经能够使用lw_new和lw_delete函数创建和删除任何类的对象,并且自动调用其构造函数和析构函数了,本篇文章相关代码可以到这里下载。

下篇文章我们将讨论继承。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值