xto*_*ofl 7 c++ printf type-conversion variadic-functions
考虑这段代码片段:
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 );
Run Code Online (Sandbox Code Playgroud)
此片段会产生"直观"输出"aha".但我不知道这是如何工作的:
CStringA*被解释为const char*operator (const char*)它,为什么不能为我自己的类调用呢?有人可以解释一下吗?
编辑:添加了一个虚拟的可变参数函数,将其参数视为const char*s.看哪 - 它到达my争论时甚至会崩溃......
C++ 98标准§5.2.2/ 7的相关文本:
在参数表达式上执行左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)标准转换.在这些转换之后,如果参数没有算术,枚举,指针,成员指针或类类型,则程序格式错误.如果参数具有非POD类类型(第9节),则行为未定义.
所以正式的行为是不明确的.
但是,给定的编译器可以提供任意数量的语言扩展,而Visual C++则可以.在MSDN库文档中的Visual C++如下行为,对于传递参数...:
- 如果实际参数的类型为float,则在函数调用之前将其提升为double类型.
- 使用整数提升将任何有符号或无符号的char,short,枚举类型或位字段转换为signed或unsigned int.
- 类类型的任何参数都通过值作为数据结构传递; 副本是通过二进制复制而不是通过调用类的复制构造函数(如果存在)来创建的.
这没有提到任何关于应用用户定义的转换的Visual C++.
这可能是CString::Format你真正感兴趣的功能,取决于上面的最后一点.
干杯&hth.,
您正在做的是未定义的行为,并且是您的编译器提供的非标准扩展或纯粹的运气.我猜测CString将字符串数据存储为结构中的第一个元素,因此读取CString它就好像它是a char *产生一个有效的以null结尾的字符串.