为什么cout << "hello"选择operator<<的非成员版本?
Why does cout << "hello" choose the non-member version of the operator<<?
今天我试图了解与 operator<< 及其重载相关的事情。
让我们看一下这段代码:
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 对象没有成员 operator<< 接受 const char[]?
此外,在第四行我们得到一个错误,因为没有非成员运算符<< 重载需要一个整数。
- 为什么没有接受整数的非成员运算符<<?
最后但并非最不重要的一点
- 为什么
cout << “hello”
选择运营商的非会员版本<< ?
可能是因为有一个特定的非成员运算符<<重载 这是 const char[] 的一个很好的候选者,而不是成员运算符<<重载需要 void*?
Why isn't there a member operator<< for the cout object which takes a const char[]?
不需要,因为 const char[]
会衰减到 const char*
。
Why isn't there a non-member operator<< which takes an integer?
这不会让我们在日常生活中变得模棱两可吗?
Why does cout << “hello” choose the non-member version of the operator<< ?
因为它比转换为 void const*
更匹配,后者需要类型转换。
Why isn't there a member operator<<
for the cout
object which takes a const char[]
?
字符串单独处理。为 std::basic_string
创建成员运算符将要求所有流都依赖于 std::basic_string
功能,这并不总是可取的。所有成员运算符都用于内置语言类型,但 std::basic_string
是 class,因此它具有非成员运算符重载。有人可能会争辩说 const char[]
(衰减到 const char*
)是一种内置类型,但是 operator<<
流 const char*
类似于 std::basic_string
,它不会将这些实现拆分到库的两个不同区域是没有意义的。处理字符串的功能,无论是使用数组还是 classes,通常都组合在一起。
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 the operator<<
?
Maybe because there is a particular non-member operator<<
overload which is a good candidate for a const char[]
, rather than the member-operator<<
overload which takes a void*
?
这正是原因所在。类型化的 const char[]
参数比非类型化的 void*
指针更适合窄字符串文字。因此,如果两个运算符都在范围内(并且 const char[]
重载仅在使用 #include <string>
时才在范围内),那么编译器将选择更匹配的重载。
IIRC const char *
重载的非成员性是由于技术原因:委员会希望宽字符流也提供 const char*
输出,但如果您同时提供 operator<<(const charT*)
和 operator<<(const char *)
作为成员,那么窄字符流将是格式错误的,因为它具有两个具有相同签名的成员函数。让他们成为非成员解决了这个问题——他们现在只会在重载解决方案中解决这个问题,如果有歧义,你只需添加一个更专业的重载。
今天我试图了解与 operator<< 及其重载相关的事情。
让我们看一下这段代码:
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 对象没有成员 operator<< 接受 const char[]?
此外,在第四行我们得到一个错误,因为没有非成员运算符<< 重载需要一个整数。
- 为什么没有接受整数的非成员运算符<<?
最后但并非最不重要的一点
- 为什么
cout << “hello”
选择运营商的非会员版本<< ?
可能是因为有一个特定的非成员运算符<<重载 这是 const char[] 的一个很好的候选者,而不是成员运算符<<重载需要 void*?
Why isn't there a member operator<< for the cout object which takes a const char[]?
不需要,因为 const char[]
会衰减到 const char*
。
Why isn't there a non-member operator<< which takes an integer?
这不会让我们在日常生活中变得模棱两可吗?
Why does cout << “hello” choose the non-member version of the operator<< ?
因为它比转换为 void const*
更匹配,后者需要类型转换。
Why isn't there a member
operator<<
for thecout
object which takes aconst char[]
?
字符串单独处理。为 std::basic_string
创建成员运算符将要求所有流都依赖于 std::basic_string
功能,这并不总是可取的。所有成员运算符都用于内置语言类型,但 std::basic_string
是 class,因此它具有非成员运算符重载。有人可能会争辩说 const char[]
(衰减到 const char*
)是一种内置类型,但是 operator<<
流 const char*
类似于 std::basic_string
,它不会将这些实现拆分到库的两个不同区域是没有意义的。处理字符串的功能,无论是使用数组还是 classes,通常都组合在一起。
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>
时才在范围内),那么编译器将选择更匹配的重载。
IIRC const char *
重载的非成员性是由于技术原因:委员会希望宽字符流也提供 const char*
输出,但如果您同时提供 operator<<(const charT*)
和 operator<<(const char *)
作为成员,那么窄字符流将是格式错误的,因为它具有两个具有相同签名的成员函数。让他们成为非成员解决了这个问题——他们现在只会在重载解决方案中解决这个问题,如果有歧义,你只需添加一个更专业的重载。