为什么 Visual C++ 编译器在这里调用错误的重载?
我有一个 ostream 的子类,用于定义格式化缓冲区。有时我想创建一个临时的并立即使用通常的 << 运算符将一个字符串插入其中,如下所示:
M2Stream() << "the string";
不幸的是,程序调用 operator<<(ostream, void *) 成员重载,而不是 operator<<(ostream, const char *) 非成员重载。
我编写了下面的示例作为测试,我在其中定义了自己的 M2Stream 类来重现问题。
我认为问题在于 M2Stream() 表达式会产生一个临时的,这会导致编译器更喜欢 void * 重载。但为什么?事实证明,如果我为非成员重载 const M2Stream & 设置第一个参数,我会感到模棱两可。
另一个奇怪的事情是,如果我首先定义一个 const char * 类型的变量然后调用它,而不是文字 char 字符串,它会调用所需的 const char * 重载,如下所示:
const char *s = "char string variable";
M2Stream() << s;
就好像文字字符串的类型与 const char * 变量不同!他们不应该是一样的吗?当我使用临时和文字字符字符串时,为什么编译器会调用 void * 重载?
#include "stdafx.h"
#include <iostream>
using namespace std;
class M2Stream
{
public:
M2Stream &operator<<(void *vp)
{
cout << "M2Stream bad operator<<(void *) called with " << (const char *) vp << endl;
return *this;
}
};
/* If I make first arg const M2Stream &os, I get
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(39) : error C2666: 'M2Stream::operator <<' : 2 overloads have similar conversions
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(13): could be 'M2Stream &M2Stream::operator <<(void *)'
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(20): or 'const M2Stream &operator <<(const M2Stream &,const char *)'
while trying to match the argument list '(M2Stream, const char [45])'
note: qualification adjustment (const/volatile) may be causing the ambiguity
*/
const M2Stream & operator<<(M2Stream &os, const char *val)
{
cout << "M2Stream good operator<<(const char *) called with " << val << endl;
return os;
}
int main(int argc, char argv[])
{
// This line calls void * overload, outputs: M2Stream bad operator<<(void *) called with literal char string on constructed temporary
M2Stream() << "literal char string on constructed temporary";
const char *s = "char string variable";
// This line calls the const char * overload, and outputs: M2Stream good operator<<(const char *) called with char string variable
M2Stream() << s;
// This line calls the const char * overload, and outputs: M2Stream good operator<<(const char *) called with literal char string on prebuilt object
M2Stream m;
m << "literal char string on prebuilt object";
return 0;
}
输出:
M2Stream bad operator<<(void *) called with literal char string on constructed temporary
M2Stream good operator<<(const char *) called with char string variable
M2Stream good operator<<(const char *) called with literal char string on prebuilt object