我正在阅读 A.T. 的一本 OOC 书。 Schreiner
,我卡在了这段代码的以下一行:
struct Class {
size_t size;
void *(* ctor) (void *self, va_list *app);
};
struct String {
const void *class; // must be first
char *text;
};
void *new(const void *_class, ...) {
const struct Class *class = _class; // assign the address of `struct String` class
void *p = calloc(1, class->size); // allocate the sizeof(struct String);
assert(p);
*(const struct Class **)p = class; // Force the conversion of p and set the argument `class` as the value of this pointer.
if(class->ctor) {
va_list ap;
va_start(ap, _class);
p = class->ctor(p, &ap); // Now what is `p` here, a `struct String` or `struct Class`.
// and if it is `struct Class` then how it convert to `struct String` in `String_ctor` function
// given below.
va_end(ap);
}
return p;
}
static void *String_ctor(void *_self, va_list *app) {
struct String *self = _self;
const char *text = va_arg(*app, const char *);
self->text = malloc(strlen(text) + 1);
assert(self->text);
strcpy(self->text, text);
return self;
}
// Initialization
static const struct Class _String = {
sizeof(struct String),
String_ctor
};
const void *String = &_String;
// Call like this:
int main(void) {
void *a = new(String, "some text");
}
现在,如您所见,在 new
函数中,以下行 p = class->ctor(p, &ap)
让我很困惑。你可以看到上面描述的评论。
另外,我想知道 struct String
的 const void *class
是如何像书上说的那样被 new
函数初始化的。
最佳答案
p
被分配给class->ctor
的返回值,它被声明为void *
所以它是一个 void指针。查看String_ctor
的定义,您可以看到它返回self
,它是一个String *
,所以在这种情况下您得到一个void *
可以安全地转换为String *
这是通过
*(const struct Class **)p = class;
实现的。由于class
是String
的第一个成员,因此指向String
的指针将与指向其class< 的指针具有相同的地址
字段。因此,当您将p
转换为Class **
并写入它时,您正在写入它的class
字段。
关于C中的构造函数和析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23591027/