2012-05-01 14 views
7

Todo estaba bien hasta que moví mis objetos a un espacio de nombres. Y ahora el compilador afirma que mis atributos de Color son privados.C++ - ostream, friends y namespaces

Pensé que el objetivo de los amigos era compartir información encapsulada con los que una clase se hiciera amiga.

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

error:

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) ===| 

Entonces, ¿cuál es el trato? Estoy usando Code :: Blocks como mi IDE. Y ni siquiera mostrará ninguna propiedad o método cuando utilizo el operador de punto en el parámetro "color". Esto es obviamente un signo de que algo va mal ... en alguna parte.

He tomado la sobrecarga del operador amigo y compila muy bien. Ningún error en otro lugar. ¿Qué ofrece?

Se declara como sigue:

namespace st{ 

class Color { 

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

}; 
}; 

Editar:

En mi CPP ahora he hecho esto:

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 
} 

Sin errores de compilación, pero es normal que tal situación para usar el espacio de nombres nuevamente en el encabezado? ¿O está completamente fuera de lo que debería estar haciendo?

Edit: @Rob gracias por su aporte también!

+0

¿Qué quiere decir con "movido mis objetos a un espacio de nombres"? – jedwards

+0

Mover el objeto entre un espacio de nombres. I.E namespace st {class ...} – Sidar

+0

No use el espacio de nombres nuevamente en la definición de 'operator <<'. Esto no debería ser necesario. – pmr

Respuesta

5

Debe declarar y definir sus operadores en el mismo espacio de nombres que el objeto. Todavía se encontrarán a través de Argument-Dependent-Lookup.

Una aplicación habitual se verá así:

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

Editar

Parece que usted no está declarin su operator<< en el espacio de nombres y también está definiendo fuera del espacio de nombres. He ajustado el código.

+0

Por favor, amplíe eso. ¿Algún ejemplo? Hasta ahora, el amigo ha sido declarado en el espacio de nombres st. Se declara dentro de la clase Color. – Sidar

+0

@Sidar Agregué un ejemplo. Es posible que desee agregar código a su pregunta para mostrar su problema. – pmr

+1

Estoy bastante confundido, pensé que eso es exactamente lo que estoy haciendo. La declaración se establece en el archivo cpp mientras la definición está en el encabezado. ¿En qué se diferencia esto de su ejemplo? Realmente no sé qué mostrar más. Esto es realmente todo lo que hay que hacer. – Sidar

0

También necesita calificar su operador con el espacio de nombres. Es una firma de función declarada en el espacio de nombre, por lo que para acceder a su símbolo debe agregarle el espacio de nombre.

Trate de esta manera:

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

me lanza: error: 'std :: ostream & st :: operator << (std :: ostream &, const st :: Color &)' debería haber sido declarado dentro de 'st ' – Sidar

+0

qué compilador estás usando? Esto funciona en Visual Studio Express 2010. Si esto no funciona, entonces lo que seguramente funciona es poner el cuerpo del método en el archivo h dentro del bloque de espacio de nombres. – Rob

+0

GCC. Eso es lo que hice. (mire mi edición) así que sería perfectamente correcto usar el espacio de nombres st {} en el encabezado de nuevo, y solo poner la sobrecarga del operador allí. Siento que me perdí esta información en. Todo lo demás tiene un alcance de st :: Color :: Etc. – Sidar