2012-05-01 2 views
7

Все было нормально, пока я не переместил объекты в пространство имен. И теперь компилятор утверждает, что мои атрибуты цвета являются частными.C++ - ostream, friends и namespaces

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

Color.h

friend ostream & operator << (ostream& output, const st::Color& 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: 
    ..... 

}; 
}; 

Edit:

В моей 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 спасибо за ваш вклад!

+0

Что вы имеете в виду под «пошевелил объекты в пространстве имен»? – jedwards

+0

Перемещение объекта между пространством имен. I.E namespace st {class ...} – Sidar

+0

Не используйте пространство имен еще раз в определении 'operator <<'. Это не обязательно. – pmr

ответ

5

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

Обычная реализация будет выглядеть следующим образом:

/// 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<< в пространстве имен и также определяя его вне пространства имен. Я скорректировал код.

+0

Просьба подробно остановиться на этом. Любой пример? До сих пор друг объявлен вместе в пространстве имен st. Он объявлен в классе Color. – Sidar

+0

@ Сидар Я добавил пример. Вы можете добавить код в свой вопрос, чтобы показать свою проблему. – pmr

+1

Я довольно смущен, я думал, что это именно то, что я делаю. Объявление задается в файле cpp, а определение - в заголовке. Как это отличается от вашего примера? Я действительно не знаю, что показать больше. Это действительно все, что нужно. – Sidar

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

throws me: error: 'std :: ostream & st :: operator << (std :: ostream &, const st :: Color &)' должен был быть объявлен внутри 'st ' – Sidar

+0

Какой компилятор вы используете? Это работает в Visual Studio Express 2010. Если это не сработает, то то, что обязательно работает, - это поместить тело метода в файл h внутри блока пространства имен. – Rob

+0

GCC. Это что я сделал. (посмотрите на мое редактирование), так что было бы прекрасно использовать пространство имен st {} в самом заголовке еще раз и только перегружать оператор там? Я чувствую, что я пропустил эту информацию на. Все остальное только что связано с st :: Color :: Etc. – Sidar