我正在读一本关于在C中实现OOP的书,并找到了这段代码:
void delete (void * self)
{
const struct Class ** cp = self;
if (self && * cp && (* cp) -> dtor)
self = (* cp) -> dtor(self);
free(self);
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么作者创建了一个双指针而不是像这样的单个指针
void delete (void * self)
{
const struct Class * cp = self;
if (self && cp && cp -> dtor)
self = cp -> dtor(self);
free(self);
}
Run Code Online (Sandbox Code Playgroud)
有什么区别吗?
在作者的对象系统中,每个对象struct都包含指向其类的第一个元素:
typedef struct Object1 {
Class *myclass;
int data;
} Object1;
typedef struct Object2 {
Class *myclass;
double data;
} Object2;
Run Code Online (Sandbox Code Playgroud)
这意味着通过将void *指向任何对象的Class **指针视为指针,可以在不知道对象的实际类型的情况下遵循类指针.这是标准允许的,因为:
6.7.2.1结构和联合规范
15 [...]指向结构对象的指针(适当转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然.[...]
因此,任何指针Object1 *或Object2 *等等可以被转换为一个指向它的第一个元素,即Class **(自的任一的类型是第一个元素Class *的指针的第一个元素是类型的Class **).请参阅在C中,指向结构的指针是否始终指向其第一个成员?欲获得更多信息.
这是一种法律方法,但有点难以遵循.相当于写
typedef struct BaseObject {
Class *myclass;
} BaseObject;
Run Code Online (Sandbox Code Playgroud)
并要求每个对象struct包含一个BaseObject实例作为其第一个成员; 在delete随后的功能会投self来BaseObject *写((BaseObject *) self)->myclass->dtor:
void delete (void * self)
{
BaseObject *base = self;
if (self && base->myclass && base->myclass—>dtor)
self = base->myclass->dtor(self);
free(self);
}
Run Code Online (Sandbox Code Playgroud)