今天我试图了解与运算符<<及其重载相关的事情。
让我们看一下这段代码:
cout.operator<<("hello"); // +16 overloads -> implicit conversion to void*
cout.operator<<(123); // +16 overloads
operator<<(cout,"hello"); // +13 overloads
operator<<(cout, 123); // ERROR: no overload
cout << "hello"; // +13 overloads ---> non-member version!
cout << 123; // +16 overloads ---> member version!
感谢 Visual Studio 的 Intellisense,我可以检测每一个它可以提供多少重载。
我得出的结论是:
- 非成员运算符<<重载为13
- 成员运算符<<重载(对于 cout)是 16
我有这些问题:
正如您从最后两行中看到的,当使用带有 const char[] 的 cout 时,选择了非成员重载。
- 为什么 cout 对象没有一个成员运算符<<,它接受一个 const char[]?
此外,在第四行我们得到一个错误,因为没有非成员运算符<< 重载需要一个整数。
- 为什么没有接受整数的非成员运算符<<?
最后一点
- 为什么
cout << “hello”
选择运营商的非成员(member)版本<< ?
可能是因为有一个特定的非成员运算符<<重载是const char[]的良好候选者,而不是采用的成员运算符<<重载无效*?
最佳答案
Why isn't there a member
operator<<
for thecout
object which takes aconst char[]
?
字符串是分开处理的。为 std::basic_string
创建成员运算符将要求所有流都依赖于 std::basic_string
功能,这并不总是可取的。所有成员运算符都用于内置语言类型,但 std::basic_string
相反,它是一个类,因此它具有非成员运算符重载。有人可能会争辩说 const char[]
(衰减为 const char*
)是内置类型,但是 operator<<
溪流 const char*
类似于 std::basic_string
,将这些实现拆分到库的两个不同区域是没有意义的。处理字符串的功能,无论是使用数组还是类,通常都组合在一起。
Why isn't there a non-member operator<< which takes an integer?
因为不需要一个。它已经作为成员运算符存在。您不应该直接 调用成员运算符(除非您需要,而您的示例不需要)。您应该正常使用运算符 ( stream << ...
) 并让重载决策根据参数、作用域等选择正确的成员或非成员运算符。如果您考虑一下,非成员重载会导致歧义错误。应该stream << 123
调用stream.operator<<(123)
或 ::operator<<(stream, 123)
?只能有一个选择,否则编译失败。
Why does
cout << “hello”
choose the non-member version of theoperator<<
? Maybe because there is a particular non-memberoperator<<
overload which is a good candidate for aconst char[]
, rather than the member-operator<<
overload which takes avoid*
?
这正是原因所在。类型 const char[]
参数更适合窄字符串文字,然后是未类型化的 void*
指针。因此,如果两个运算符都在范围内(并且 const char[]
重载仅在使用 #include <string>
时才在范围内),那么编译器将选择更匹配的重载。
关于c++ - 为什么cout << "hello"选择operator<<的非成员版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39336769/