将变量参数传递给语句时,不会传递类型信息。
想象一下这个使用字符串对象的示例(我使用的是 MFC/ATL 的 CString)
CString name = "kevin";
printf("Hi %s", name);
printf 语句(或 CString)如何知道获取/返回 LPCSTR 运算符,从而获得指向字符串的指针,而不是指向对象的指针?
我正在尝试编写自己的字符串类(它需要在一个巨大的项目中替换 CString),但是当我执行上面的 printf 时,它最终会出现乱码,因为它没有获得正确的名称值。
最佳答案
真正的答案与对运算符 LPCTSTR () 的隐式调用无关,我认为它的实际工作方式很聪明。
要实现字符串类,当然需要字符串的数据缓冲区,以及其他一些数据字段,例如字符串的长度,可能分配了多少内存,可能是引用计数等。
但是如何让可变参数函数在传递 CString 参数时看到 C 风格的字符串呢?您可以将数据缓冲区字段(指向 char* 的指针)作为第一个成员,但随后所有其他字段(如字符串长度)也会意外地插入堆栈,就好像它们是额外的函数参数一样。
因此,您尝试的下一步是将所有字段打包到单个内存结构中,该内存结构与字符串字符数据缓冲区一起分配。如果此数据缓冲区位于聚合结构的开头,则需要 C 字符串的可变参数函数将看到此结构的开头。如果将终端 null 放置在数据缓冲区的末尾、其他数据字段之前,则 printf 将在遇到您不希望它看到的数据之前停止读取字符串数据,并且一切正常!
但是你意识到有一个新问题——字符数据缓冲区的长度是可变的,并且“长度”字段现在位于内存中字符数据之后,因此你需要知道“长度”为了知道在哪里可以找到“长度”字段。
那么您可以将“length”和所有其他额外字段移动到结构的开头,在内存中字符数据之前吗?当然不是,printf 现在会看到在真实字符串的开头添加了一些有趣的字符(甚至是 null)。
但这就是 CString 的作用。但是,它的单个成员变量是一个指针,不是指向聚合结构的开头,而是指向其中字符数据开始的内存位置。
并且由于数据字段(没有字符缓冲区)具有固定大小,因此字符串类知道如何在内存中访问它们,只要给出其指向 char 的指针(这些字段位于距 char 指针的负偏移量处) 。当然,当它释放其聚合结构时,该类还需要计算其原始内存分配的开始位置,而不仅仅是使用其指向 char 的指针。
关于c++ - 变量参数列表如何与 C++ 中的重载对象一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33661520/