4

我正在阅读一本关于在 C 中实现 OOP 的书,并找到了以下代码:

void delete (void * self)
{ 
    const struct Class ** cp = self;
    if (self && * cp && (* cp) -> dtor)
        self = (* cp) -> dtor(self);
    free(self);
}

我想知道为什么作者创建了一个双指针而不是像这样的单指针

void delete (void * self)
{ 
    const struct Class * cp = self;
    if (self && cp && cp -> dtor)
        self = cp -> dtor(self);
    free(self);
}

有什么区别吗?

4

3 回答 3

5

在作者的对象系统中,每个对象结构都包含一个指向其类的指针作为其第一个元素:

typedef struct Object1 {
    Class *myclass;
    int data;
} Object1;

typedef struct Object2 {
    Class *myclass;
    double data;
} Object2;

这意味着通过将void *指向任何对象的指针视为Class **指针,可以在不知道对象的实际类型的情况下跟踪类指针。这是标准允许的,因为:

6.7.2.1 结构和联合说明符

15 [...] 指向结构对象的指针,经过适当转换,指向其初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。[...]

因此,任何指针等都Object1 *可以Object2 *转换为指向其第一个元素的指针,即Class **(因为任何一个的第一个元素是 type Class *,指向第一个元素的指针是 type Class **)。请参阅在 C 中,指向结构的指针是否总是指向其第一个成员?了解更多信息。

这是一种合法的方法,但有点难以遵循。一个等价物是写

typedef struct BaseObject {
    Class *myclass;
} BaseObject;

并要求每个对象结构都包含一个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);
}
于 2012-08-20T10:24:29.333 回答
1

在这个系统中,每个对象在第一个字段中都包含一个指向其类的指针。实际上,Class **c = self从对象实例中获取类结构。

于 2012-08-20T10:26:26.697 回答
0

由于结构设计:

*(const struct Class **)p=class;

在那里: http ://humelab.googlecode.com/svn-history/r3/trunk/ooc/new.c

如在

void * new(const void *_class,...)
{
 const struct Class *class=_class;
 void *p=calloc(1,class->size);
 assert(p);
 *(const struct Class **)p=class;  //<------look here!

 if(class->ctor)
 {
  va_list ap;
  va_start(ap,_class);
  p=class->ctor(p,&ap);
  va_end(ap);
 }
 return p;
}
于 2012-08-20T10:25:44.143 回答