来自void*的双指针和单指针?

Ash*_*egi 4 c pointers

我正在读一本关于在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)

有什么区别吗?

eca*_*mur 5

在作者的对象系统中,每个对象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随后的功能会投selfBaseObject *((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)