【问题标题】:Overloading ostream operator (<<) for class defined within a namespace为命名空间中定义的类重载 ostream 运算符 (<<)
【发布时间】:2015-04-26 23:31:14
【问题描述】:

考虑 bar.h

#include <iostream>

namespace foo {

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

}

考虑 bar.cc

#include "bar.h"

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

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

  return output;
}

为什么 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)

我通过将 operator 的实现嵌入到 foo 命名空间中解决了这个问题,即:

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

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

  return output;
}
}

然而……这是解决这个问题的正确方法吗?这种方法不是泄露了实现的细节吗?

【问题讨论】:

  • 你也可以在定义中写std::ostream&amp; foo::operator&lt;&lt;(...,而不是命名空间块。如果它与预先声明的函数不匹配,则具有编译错误的优点

标签: c++ namespaces operator-overloading ostream


【解决方案1】:

问题:

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

答案:

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

问题:

这种方法不是泄露了实现的细节吗?

答案:

一点也不。

线

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

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

如果您希望该函数成为一个全局函数,在 foo 命名空间之外,您必须使用:

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_;
   };
}

【讨论】:

    【解决方案2】:

    因为你的类 Bar 是 foo 命名空间的一部分,你需要在同一个命名空间中定义函数。

    如果您担心隐藏实现细节,您仍然可以在 bar.cc 中定义函数

    bar.cc

    #include "foo.h"
    
    namespace foo
    {
    
    std::ostream& operator<<(std::ostream& output, const Bar &in)
    {
            output << "Bar x=" << in.x << std::endl;
    
            return output;
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 2010-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-04
      相关资源
      最近更新 更多