c++ - 变量参数列表如何与 C++ 中的重载对象一起使用?

标签 c++ string mfc operator-overloading

将变量参数传递给语句时,不会传递类型信息。

想象一下这个使用字符串对象的示例(我使用的是 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/

相关文章:

c++ - 为什么 BOOST_TEST((Iterator == Iterator)) 需要额外的括号?

c - 指向地址 C 的字符串

c++ - 到 ATL 的静态链接总是失败

c++ - MFC 错误如 A reference that is not to 'const' cannot be bound to a non-lvalue

c# - 2个计时器,一个落后另一个n秒

c# - 如何获得鼠标滚轮垂直滚动率

C++ 将字符串转换为其 ASCII 表示形式

c++ - 引用重载,而不是唯一的按值传递+ std::move?

string - Excel VBA 复杂字符串替换

c++ - C++ 和字符串 vector 中的内存泄漏或其他问题