考虑这个代码片段:
struct My {
operator const char*()const{ return "my"; }
} my;
CStringA s( "aha" );
printf("%s %s", s, my );
// another variadic function to get rid of comments about printf :)
void foo( int i, ... ) {
va_list vars;
va_start(vars, i);
for( const char* p = va_arg(vars,const char*)
; p != NULL
; p=va_arg(vars,const char*) )
{
std::cout << p << std::endl;
}
va_end(vars);
}
foo( 1, s, my );
该代码片段会产生“直观”的输出“aha”。但我不知道这是如何工作的:
- 如果可变参数函数调用被转换为推送参数的指针,printf 将收到一个
CStringA*
这被解释为const char*
- 如果可变参数函数调用正在调用
operator (const char*)
就它而言,为什么我自己的班级不这样做呢?
有人可以解释一下吗?
编辑:添加了一个虚拟变量函数,将其参数视为const char*
s。看吧 - 当它到达时它甚至崩溃了my
争论...
C++98标准§5.2.2/7的相关文本:
左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换是对参数表达式执行的。在这些转换之后,如果参数没有算术、枚举、指针、成员指针或类类型,则程序格式错误。如果参数具有非 POD 类类型(第 9 条),则行为未定义。
So 正式行为是未定义的.
然而,给定的编译器可以提供任意数量的语言扩展,而 Visual C++ 就是如此。这MSDN 库 http://msdn.microsoft.com/en-us/library/z11y6be4.aspx记录 Visual C++ 的行为,如下所示,将参数传递给...
:
- 如果实际参数的类型为 float,则在函数调用之前将其提升为 double 类型。
- 任何有符号或无符号 char、短整型、枚举类型或位字段都会使用整数提升转换为有符号或无符号 int。
- 类类型的任何参数都作为数据结构按值传递;该副本是通过二进制复制而不是通过调用类的复制构造函数(如果存在)创建的。
这没有提到任何有关 Visual C++ 应用用户定义的转换的内容。
MS CString
是“巧妙”布局的,因此它的 POD 表示正是指向其以 null 结尾的字符串的指针。 (sizeof(CStringA) == sizeof(char*)
) 当它用于anyprintf 风格的函数该函数刚刚获取传递的字符指针。
所以这是有效的,因为上面的最后一点和方式CString
已布置。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)