C语言也能面向对象(二)——new和delete

Technorati 标签: c,c语言,面向对象,oo,object-oriented
本文版权所有,转载请注明出处和作者联系方式。

作者:孙华明

联系方式: wormsun at gmail.com

上篇我们介绍了如何使用结构体写一个简单的类animal,并使用animal animal_create(void)和void animal_destroy(animal self)来创建和删除animal类的对象。

在C++中创建和删除对象时使用的是new和delete操作符,并会自动调用类的构造函数和析构函数初始化和析构对象,那么使用C语言如何实现这样的机制呢?我们可以用函数模拟new和delete,定义两个函数:lw_new和lw_delete(“lw”意为light-weight,轻量级的意思)。

使用lw_new创建类的对象时,需要为对象申请内存空间,并且需要初始化该对象,所以lw_new函数至少需要知道该类的对象需要多大的内存空间,以及该类的构造函数是谁。我们可以将这些信息封装到一个结构体中,称之为类信息结构体,如下(以上篇介绍的animal类为例):

typedef struct _animal_klass_info animal_klass_info;
struct _animal_klass_info
{
size_t size;    /*animal's size*/
animal* (*ctor)(animal* self); /*constructor*/
};

然后我们创建一个该结构体的对象(称之为类信息),将animal类的内存大小、构造函数等信息存入到对象中,再使用一个全局的指针指向该对象(称之为全局类信息指针),如下:

extern animal_klass_info* animal_klass;
static animal_klass_info local_animal_klass =
{
sizeof(animal),
animal_ctor,
};
animal_klass_info* animal_klass = &local_animal_klass;

这样在创建animal类的对象时,我们只需要将animal类的全局类信息指针animal_klass传入到 lw_new函数中,lw_new函数就能够申请内存空间,并自动调用构造函数初始化对象了,lw_new的实现如下:

animal* lw_new(animal_klass_info* klass)
{
animal* p = ANIMAL(malloc(klass->size));
return klass->ctor(p);
}

现在可以使用lw_new创建animal类的对象了,如下:

animal* animal1 = lw_new(animal_klass);

那么如何使用lw_delete函数删除对象,并自动调用析构函数呢?

在C++中删除对象时,传递给delete操作符的参数只有对象的地址,所以我们传递给lw_delete函数的也只能是对象的地址。使用对象地址我们可以释放对象占用的内存空间,但如何调用对象的析构函数呢?

我们可以将析构函数的地址加入到类信息结构体中,还是以animal类为例,将其类信息结构体修改为:

typedef struct _animal_klass_info animal_klass_info;
struct _animal_klass_info
{
size_t size;    /*animal's size*/
animal* (*ctor)(animal* self); /*constructor*/
animal* (*dtor)(animal* self); /*destructor*/
};

在创建类信息时加入析构函数的地址,如下:

static animal_klass_info local_animal_klass =
{
sizeof(animal),
animal_ctor,
animal_dtor,
};

然后在animal类中加入一个类信息结构体的指针,用来保存animal类信息的地址。修改animal类定义如下:

typedef struct _animal animal;
struct _animal
{
/*klass info*/
animal_klass_info* klass;

/*private data*/
char name[256];
int weight;
};

在lw_new函数中初始化animal类的类信息结构体指针,如下:

animal* lw_new(animal_klass_info* klass)
{
animal* p = ANIMAL(malloc(klass->size));
p->klass = klass;
return klass->ctor(p);
}

这样lw_delete函数就能够根据传入的对象的地址,取得相应的类信息地址,进而取得析构函数了,lw_delete实现如下:

void lw_delete(animal* self)
{
if(self)
{
free(self->klass->dtor(self));
}
}

至此,lw_new和lw_delete都已经实现了,我们测试一下吧.

int main(int argc, char* argv)
{
argc;
argv;

animal* animal1 = NULL;
animal* animal2 = 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);
return 0;
}

完整的代码可以在此处下载。

大家可以看出我们目前实现的lw_new和lw_delete只能用于创建和删除animal类的对象。如何实现通用的lw_new和lw_delete呢?这就是下篇我们将要介绍的内容。
原文链接: https://www.cnblogs.com/wormsun/archive/2011/04/18/2263566.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/24223

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午2:02
下一篇 2023年2月8日 上午2:03

相关推荐