C ++中的流操纵器如何成为函数?

时间:2014-04-13 13:07:46

标签: c++ manipulators

在C ++中调用函数时,会写入函数的名称,然后是(),以将其区分为函数调用。为什么我不能以同样的方式调用流操纵函数

为什么不允许这样做?:

cout << "Hello!" << endl();

不是endl变量持有\n

谢谢!

3 个答案:

答案 0 :(得分:2)

操纵器是专门设计用于与流对象上的插入(&lt;&lt;&lt;&lt;&quot;&)和提取(&gt;&gt;)运算符结合使用的函数,例如:

cout << boolalpha;

它们仍然是常规函数,也可以使用流对象作为参数调用为任何其他函数,例如:

boolalpha (cout);

因此,在您的代码中,您可以执行

cout << "Hello!";
endl(cout);

而不是

cout << "Hello!" << endl;

Source

答案 1 :(得分:2)

流操纵器功能。因此,可以使用调用运算符()调用 。以下是您在广告联盟中呼叫std::endl的方法:

std::endl(std::cout);

这是必须为您要使用的每个流std::endl调用的方式。这是因为std::endl是一个返回对流对象的引用的函数。这是一种非常古怪的方式,所以有一个方便的功能来简化语法:

std::ostream& operator<<(std::ostream& (*manip)(std::ostream&));

这是operator<<()的重载,它的左侧是一个流,右侧是一个操纵器。 std::endl在技术上是一个函数,因此可以将其转换为函数指针。

在这个重载的实现中,manip几乎被我调用了。这允许语法如:

std::cout << "Hello, World" << std::endl;

如果你继续使用call运算符调用std::endl,它将返回对流的引用。还有另一个operator<<()重载,它以const void*为参数。那将是无意中被称为的过载。

std::cout << std::endl(std::cout); // prints a newline then an address

答案 2 :(得分:1)

  

不是一个持有\ n?

的变量

不,不是。 std::endl是全局命名空间

中定义的函数
  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

在表达式std::cout << endl_or_something中,<<的右侧是对operator<<的调用的参数(第一个参数是std::ostream隐式)。所以endl_or_something应该是int,double或其他类型,可以转换为operator<<的可能参数之一。这个运算符的重载版本带有指向函数的指针(引用std::ostream的函数并返回对std::ostream的引用):

  // [27.6.2.5] formatted output
  // [27.6.2.5.3]  basic_ostream::operator<<
  //@{
  /**
   *  @brief  Interface for manipulators.
   *
   *  Manipulators such as @c std::endl and @c std::hex use these
   *  functions in constructs like "std::cout << std::endl".  For more
   *  information, see the iomanip header.
  */
  __ostream_type&
  operator<<(__ostream_type& (*__pf)(__ostream_type&))
  {
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// The inserters for manipulators are *not* formatted output functions.
return __pf(*this);
  }

由于std::endl签名匹配,因此可以在表达式

中使用
std::cout << "Hello!" << std::endl;

或等效

std::cout << "Hello!";
std::endl( std::cout);

但是请注意,当需要简单的换行符时,通常会错误地使用此操纵器,从而导致缓冲性能较差。在这种情况下,只使用"\n"


  

为什么不允许这样做?:

cout << "Hello!" << endl();

std :: endl接受一个参数std :: ostream。您可以看到它可以通过以下方式调用:

return __pf(*this);

表示

return std::endl( *this); // std::endl( std::cout);

没有 std::endl 的版本不带参数,因此可以使用

调用
std::endl()

在表达

std::cout << std::endl;

它表示operator<<的参数,它作为指向函数的指针传递,然后在operator<<的正文中调用。