C语言中的构造函数和析构函数
我在读a.T.Schreiner的《OOC》一书,我被困在下面这段代码里:C语言中的构造函数和析构函数,c,pointers,function-pointers,C,Pointers,Function Pointers,我在读a.T.Schreiner的《OOC》一书,我被困在下面这段代码里: 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 stru
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\u ctor
的定义,您可以看到它返回self
,这是一个String*
,因此在这种情况下,您将得到一个void*
,可以安全地转换为String*
*(const struct Class**)p=Class实现的代码>。由于类
是字符串
的第一个成员,因此指向字符串
的指针将与指向其类
字段的指针具有相同的地址。因此,当您将p
转换为Class**
并写入时,您正在写入其Class
字段
p
既不是struct String
也不是struct Class
。这是一个指针。它指向一块内存。如何解释这种记忆是一个有趣的问题
假设我们传递实现字符串的struct类
对象的地址,第一个calloc
调用将分配一块大小为struct string
的内存。因此,假设p
是指向struct String
的指针是完全合理的
new
函数对struct String
或任何其他“类”知之甚少。实际上几乎没有什么,除了这样一个事实:任何此类struct
的第一个元素都是指向struct类的指针。由于指向任何struct
的指针与指向其第一个元素(模类型)的指针相同,这使得p
也成为指向struct类的指针。所以这一行:
*(const struct Class **)p = class;
为p
指向的结构类指针指定适当的值
现在这条线
p = class->ctor(p, &ap);
调用构造函数,像在任何OO环境中一样向其传递“self”指针。它还将构造函数的结果再次分配给p
,可能是因为ctor可以(但不必)重新分配对象
总而言之:p
是指向struct String
的指针,new
将其解释为指向struct String
的第一个元素的指针,该元素必须是指向struct Class
的指针实际上你是对的,但我已经为此投入了2天的时间。所以对我来说知道这一点很重要。这是用一个人的前额把一个方形的钉子塞进一个圆孔里。只要说不。我有一个问题,就是想知道事情是如何运作的,我认为这至少对我有好处。你的第二点,class
是String
的第一个成员是可以的,但是在new
函数中class
是一个用const struct class
声明的变量。所以,如果你说,当你把p转换成一个类**
并写入它时,你是在写入它的类
字段。`是完全错误的。我看不出我是怎么错的p
指向一个字节长的内存块sizeof(String)
,可以安全地假设它将被当作指向一个String
(实际上,ctor就是这样做的)。所以OP正在将一个字符串*
投射到一个类**
并编写他的类指针指向它。你是对的,但是你的答案需要一点解释,你的答案也给了我一些提示来理解这个难题。你可以说new
中的class
是struct class
的一个变量,但是p
被分配给struct String
的内存,之后在*(const struct class**)p=class
中,我们分配String
创建的struct class
的地址。这就是struct String
的class
是如何初始化的。