【问题标题】:Why is operator<< function between std::ostream and char a non-member function?为什么 std::ostream 和 char 之间的 operator<< 函数是非成员函数?
【发布时间】:2015-07-07 16:54:51
【问题描述】:

当我运行以下程序时

#include <iostream>

int main()
{
   char c = 'a';
   std::cout << c << std::endl;
   std::cout.operator<<(c) << std::endl;

   return 0;
}

我得到了输出

a
97

进一步挖掘http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt,我注意到std::ostream::operator&lt;&lt;() 没有以char 作为参数类型的重载。函数调用 std::cout.operator&lt;&lt;(a) 被解析为 std::ostream::operator&lt;&lt;(int),这解释了输出。

我假设std::ostreamchar 之间的operator&lt;&lt; 函数在其他地方声明为:

std::ostream& operator<<(std::ostream& out, char c);

否则,std::cout &lt;&lt; a 将解析为 std::ostream::operator&lt;&lt;(int)

我的问题是为什么声明/定义为非成员函数?是否有任何已知问题阻止它成为成员函数?

【问题讨论】:

  • 可能是因为字符类型模板参数?通过使用语言环境的widen,此函数可以对任何字符类型具有相同(“高效”)的实现。
  • 有趣的话题。可能是what was discussed here 不起作用的原因。
  • @dyp,这似乎不太令人信服。
  • 好吧,现在对于所有流,我们有一个 operator&lt;&lt; 采用 charT 和一个 operator&lt;&lt; 采用 char。由于charT 可以——而且经常是——char,作为成员,这将是一件棘手的事情。

标签: c++ c++11 ostream


【解决方案1】:

std::basic_ostream 的插入器集包括用于将charsigned charunsigned char 等插入basic_ostream&lt;char, ...&gt; 流的部分特化。请注意,这些特化仅适用于 basic_ostream&lt;char, ...&gt; 流,不适用于 basic_ostream&lt;wchar_t, ...&gt; 流或基于任何其他字符类型的流。

如果您将这些独立模板移动到主要的basic_ostream 定义中,它们将可用于basic_ostream 的所有专业化形式。显然,图书馆作者希望防止这种情况发生。

我真的不知道他们为什么要在更通用的基础上引入这些专业

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                                        char);

插入者,但显然他们有自己的理由(优化?)。

C 字符串插入器也存在同样的情况。除了更通用的插入器

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                                        const char*);

库规范还声明了更具体的

template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
                                       const char*);

等等。

【讨论】:

  • 我不确定我是否完全理解您的回答:有一个通用的 template&lt;class charT, class traits&gt; basic_ostream&lt;charT,traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;charT,traits&gt;&amp; out, char c); 函数模板适用于 wchar_t
  • @dyp:是的,但同时他们觉得有必要引入专门的专门化方法,将char 值插入char 流。我真的不知道为什么,但库规范说存在这样的专业化。
  • 我不完全确定“专业化”是否能防止重载解决问题。
  • @AnT,显然,图书馆作者想阻止这种情况发生。 很可能是原因。如果参与图书馆开发的人能对这个主题有所了解,那将会很有趣。
【解决方案2】:

一个原因是遵循 C++ 的一般建议,即首选非成员非友元函数而不是成员函数。这是 Scott Meyer 的 Effective C++ 中的第 23 项。这在stackoverflow 中进行了讨论。

【讨论】:

  • 很高兴提及这一点。许多程序员似乎并不知道这个经验法则,导致上帝对象或对象狂欢的反模式......
  • 是的,我通常从耦合的角度来考虑它,或者避免人们对某个类变得过度耦合所做的一切。我宁愿通过公共接口完成增强,这样我就不必担心有多少函数可能会改变对象的状态(影响类不变量),即使const 成员也可以提供帮助。这也使得将函数划分为各种更集中的头文件变得更加容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多