11

一切都很好,直到我将对象移动到命名空间。现在编译器声称我的 Color 属性是私有的。

我认为朋友的全部意义在于与班级的朋友分享封装的信息。

颜色.h

friend ostream & operator << (ostream& output, const st::Color& color);

颜色.cpp:

 ostream & operator <<(ostream& output, const st::Color& color) {

    output << "Colors:\nalpha\t: " << color.a << "\nred\t: "  << color.r << "\ngreen\t: " << color.g
            << "\nblue\t: " << color.b <<  "\nvalue\t: " << color.color();

    return output;
}

错误:

Color.h||In function 'std::ostream& operator<<(std::ostream&, const st::Color&)':|
Color.h|52|error: 'unsigned char st::Color::a' is private|
Color.cpp|15|error: within this context|
Color.h|49|error: 'unsigned char st::Color::r' is private|
Color.cpp|15|error: within this context|
Color.h|51|error: 'unsigned char st::Color::g' is private|
Color.cpp|15|error: within this context|
Color.h|50|error: 'unsigned char st::Color::b' is private|
Color.cpp|16|error: within this context|
||=== Build finished: 8 errors, 0 warnings (0 minutes, 1 seconds) ===|

那么交易是什么?我使用 Code::Blocks 作为我的 IDE。当我在“颜色”参数上使用点运算符时,它甚至不会显示任何属性或方法。这显然是出现问题的迹象……某处。

我已经将朋友运算符重载出来,它编译得很好。其他地方没有错误。是什么赋予了?

它声明如下:

namespace st{

class Color {

    friend ostream & operator << (ostream& output, const st::Color& color);
 public:
     ....
 private:
    .....

};
};

编辑:

在我的 CPP 中,我现在已经这样做了:

namespace st{
ostream & st::operator <<(ostream& output, const st::Color& color) {

    output << "Colors:\nalpha\t: " << color.a << "\nred\t: "  << color.r << "\ngreen\t: " << color.g
            << "\nblue\t: " << color.b <<  "\nvalue\t: " << color.color();

    return output;
}
}

st::Color::Color() {

    reset();
}

st::Color::Color(const Color& orig) {

    a = orig.a;
    r = orig.r;
    g = orig.g;
    b = orig.b;
}

void st::Color::reset() {
    a = 0;
    r = 0;
    g = 0;
    b = 0;
}
... etc
}

没有编译错误,但是这种情况在头文件中再次使用命名空间是否正常?或者这完全偏离了我应该做的事情?

编辑:@Rob 也感谢您的意见!

4

2 回答 2

10

您还需要在与对象相同的命名空间中声明和定义运算符。它们仍然可以通过 Argument-Dependent-Lookup 找到。

通常的实现如下所示:

/// header file
namespace foo {
   class A
   {
    public:
    A();

    private:
    int x_;
    friend std::ostream& operator<<(std::ostream& o, const A& a);
    };

    std::ostream& operator<<(std::ostream& o, const A& a);
} // foo

// cpp file
namespace foo {
     A::A() : x_(23) {}

     std::ostream& operator<<(std::ostream& o, const A& a){
     return o << "A: " << a.x_;
    }
} // foo


int main()
{
  foo::A a;
  std::cout << a << std::endl;
  return 0;
}

编辑

似乎您没有在命名空间中声明您operator<<,并且还在命名空间之外定义它。我已经调整了代码。

于 2012-05-01T22:34:37.627 回答
0

您还需要使用命名空间来限定您的运算符。它是在名称空间中声明的函数签名,因此要访问其符号,您需要在其前面加上名称空间。

试试这样:

namespace st {

    ostream & operator <<(ostream& output, const Color & color) {

        output << "Colors:\nalpha\t: " << color.a
               << "\nred\t: "   << color.r 
               << "\ngreen\t: " << color.g
               << "\nblue\t: "  << color.b
               << "\nvalue\t: " << color.color();

        return output;
    }
}
于 2012-05-01T22:49:56.583 回答