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