C++ - ostream, друзья и пространства имен

все было хорошо, пока я не переместил свои объекты в пространство имен. И теперь компилятор утверждает, что мои атрибуты цвета являются частными.

Я думал, что весь смысл друзей, чтобы поделиться информацией с теми, инкапсулированные в классе дружит.

цвета.h

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

цвета.cpp:

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

    output << "Colors:nalphat: " << color.a << "nredt: "  << color.r << "ngreent: " << color.g
            << "nbluet: " << color.b <<  "nvaluet: " << 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. И он даже не покажет никаких свойств или методов, когда я используйте оператор dot для параметра "color". Очевидно, это признак того, что что-то идет не так...где-то.

я взял перегрузку оператора друга, и он компилируется просто отлично. Ошибка в другом месте. Что происходит?

это объявлено следующим образом:

namespace st{

class Color {

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

};
};

Edit:

в моем CPP я теперь сделал это:

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

    output << "Colors:nalphat: " << color.a << "nredt: "  << color.r << "ngreent: " << color.g
            << "nbluet: " << color.b <<  "nvaluet: " << 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 спасибо за Ваш вклад, а также!

2 ответов


вам также необходимо объявить и определить свои операторы в том же пространстве имен, что и объект. Они все равно будут найдены через аргумент-зависимого поиска.

обычная реализация будет выглядеть так:

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

редактировать

Кажется, что вы не declarin свой operator<< в пространстве имен, а также определяют его вне пространства имен. Я скорректировал код.


вам также необходимо квалифицировать свой оператор с пространством имен. Это сигнатура функции, объявленная в пространстве имен, поэтому для доступа к ее символу вам нужно префикс пространства имен.

попробуйте так:

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