我正在学习C,主要是K&R,但现在我找到了面向对象的C pdf教程,我很着迷.我正在经历它,但我的C技能/知识可能无法完成任务.这是教程:http://www.planetpdf.com/codecuts/pdfs/ooc.pdf
我的问题来自于在pdf的前几章中查看许多不同的功能.下面是其中之一.(pdf的第14页)
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)
dtor是一个析构函数指针.但是对于我的问题,对此的了解并不是必需的.
提前致谢
有趣的pdf.
\n\n\n\n\n我的第一个问题是,为什么 **cp 是恒定的?是否有必要或只是彻底,以便代码编写者不会无意中做出任何破坏性的事情?
\n
这是必要的,这样作者就不会意外地做任何事情,是的,并且向读者传达有关指针的性质及其用途的信息代码的
\n\n\n\n\n其次,为什么 cp 是一个指向指针的指针(双星号?)。结构体类在 pdf 第 12 页上定义。我不明白为什么它不能是单个指针,因为我们似乎将 self 指针转换为类指针。
\n
看一下new()(第 13 页)创建指针的定义(与传递给p的指针相同的指针)selfdelete()):
void * new (const void * _class, ...)\n{\n const struct Class * class = _class;\n void * p = calloc(1, class \xe2\x80\x94> size);\n * (const struct Class **) p = class;\nRun Code Online (Sandbox Code Playgroud)\n\n因此,为“p”分配了空间,然后取消引用并分配了一个指针值(类中的地址;这就像取消引用并分配给 int 指针,但我们分配的不是 int,而是地址)。 这意味着 p 中的第一件事是指向其类定义的指针。 然而,p 被分配的空间不仅仅如此(它还将保存对象的实例数据)。现在考虑delete()再考虑一下:
const struct Class ** cp = self;\n if (self&&*cp&&(*cp)->dtor)\nRun Code Online (Sandbox Code Playgroud)\n\n当 cp 被取消引用时,由于它是一个指向指针的指针,所以它现在是一个指针。指针包含什么?一个地址。什么地址? 指向类定义的指针该类定义位于 p 所指向的块的开头。
\n\n这有点聪明,因为 p\ 并不是真正指向指针的指针——它分配了更大的内存块,其中包含特定的对象数据。但是,该块的开头是一个地址(类定义的地址),因此如果 p 被取消引用为指针(通过转换或 cp),您就可以访问该定义。因此,类定义仅存在于一个位置,但该类的每个实例都包含对该定义的引用。合理?如果 p 被输入为这样的结构会更清楚:
\n\nstruct object {\n struct class *class;\n [...]\n};\nRun Code Online (Sandbox Code Playgroud)\n\n然后你可以使用类似的东西p->class->dtor()来代替现有的代码delete(). 然而,这会使整体情况变得混乱并使复杂化。
\n\n\n第三,如何将 void 指针更改为类指针(或指向类指针的指针)?我觉得这个问题最能说明我对C的缺乏理解。我脑子里想象的是一个void指针占用了一定的内存,但它一定小于Class指针,因为a\xe3 \x80\x80Class 里面有很多“东西”。
\n
指针就像一个 int —— 它有一个小的、固定的大小来保存一个值。该值是内存地址。当您取消引用指针(通过*或->)时,您访问的是该地址处的内存。但由于内存地址的长度都相同(例如,64 位系统上为 8 字节),因此无论类型如何,指针本身的大小都相同。这就是对象指针“p”的神奇原理。重申一下:内存块中指向的第一件事p是一个地址,它允许它充当指向指针的指针,当取消引用时,您将获得包含类定义的内存块,即与实例数据分开p。