为名称空间中定义的类重载ostream运算符(<<)

Edu*_*rdo 2 c++ namespaces operator-overloading ostream

考虑bar.h:

#include <iostream>

namespace foo {

class Bar {
 public:
  friend std::ostream& operator <<(std::ostream& output, const Bar&);
 private:
  int xx_;
};

}
Run Code Online (Sandbox Code Playgroud)

考虑bar.cc:

#include "bar.h"

std::ostream& operator<<(std::ostream& output, const foo::Bar &in) {

  output << in.xx_ << std::endl;

  return output;
}
Run Code Online (Sandbox Code Playgroud)

为什么不能实现operator <<Bar类访问私有成员?那是:

$ icpc -c bar.cc
bar.cc(5): error #308: member "foo::Bar::xx_" (declared at line 9 of "bar.h") is inaccessible
    output << in.xx_ << std::endl;
                 ^

compilation aborted for bar.cc (code 2)
Run Code Online (Sandbox Code Playgroud)

我通过在foo命名空间内嵌入operator <<的实现来解决问题,即:

namespace foo {
std::ostream& operator<<(std::ostream& output, const foo::Bar &in) {

  output << in.xx_ << std::endl;

  return output;
}
}
Run Code Online (Sandbox Code Playgroud)

然而......这是解决这个问题的正确方法吗?这种方法不是给出了实施的细节吗?

R S*_*ahu 7

题:

这是解决这个问题的正确方法吗?

回答:

是的,这是解决问题的正确方法.

题:

这种方法不是给出了实施的细节吗?

回答:

一点也不.

这条线

friend std::ostream& operator <<(std::ostream& output, const Bar&);
Run Code Online (Sandbox Code Playgroud)

将该函数声明为定义类的名称空间中的外部函数.如果未在命名空间中定义类,则将该函数声明为全局命名空间中的外部函数.由于函数在foo命名空间中声明为外部函数,因此必须在该命名空间中定义.

如果您希望该函数是一个全局函数,在foonamesapce 之外,您必须使用:

namespace foo
{
    class Bar;
}

std::ostream& operator <<(std::ostream& output, const foo::Bar&);

namespace foo {

   class Bar {
      public:
         friend std::ostream& operator <<(std::ostream& output, const Bar&);
      private:
         int xx_;
   };
}
Run Code Online (Sandbox Code Playgroud)