2012-05-01 20 views
7

Tutto andava bene finché non ho spostato i miei oggetti in uno spazio dei nomi. E ora il compilatore afferma che i miei attributi di colore sono privati.C++ - ostream, amici e spazi dei nomi

Pensavo che il punto principale degli amici fosse condividere le informazioni incapsulate con quelle di un amico di classe.

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

errore:

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

Allora, qual è il problema? Sto usando Code :: Blocks come IDE. E non mostrerà nemmeno proprietà o metodi quando uso l'operatore punto sul parametro "colore". Questo è ovviamente un segno di qualcosa che va storto ... da qualche parte.

Ho eliminato l'operatore dell'amico e lo compila bene. Nessun errore altrove. Cosa dà?

E 'dichiarato come segue:

namespace st{ 

class Color { 

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

}; 
}; 

Edit:

Nel mio CPP ora ho fatto questo:

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 
} 

No errori di compilazione, ma è normale per un tale situazione per utilizzare nuovamente lo spazio dei nomi nell'intestazione? O è completamente fuori da quello che dovrei fare?

Modifica: @Rob grazie anche per l'input!

+0

Che cosa si intende per "spostato i miei oggetti per uno spazio dei nomi"? – jedwards

+0

Spostamento dell'oggetto tra uno spazio dei nomi. I.E namespace st {class ...} – Sidar

+0

Non utilizzare nuovamente lo spazio dei nomi nella definizione di operatore << '. Questo non dovrebbe essere necessario. – pmr

risposta

5

È necessario dichiarare e definire gli operatori nello stesso spazio dei nomi dell'oggetto. Verranno comunque trovati tramite Argoment-Dependent-Lookup.

Un solita applicazione sarà simile a questa:

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

Modifica

Sembra che non si è declarin tuo operator<< nello spazio dei nomi e stanno definendo anche al di fuori dello spazio dei nomi. Ho modificato il codice.

+0

Per favore, spiegaci. Qualche esempio? Finora l'amico è stato dichiarato witht nel namespace st. È dichiarato all'interno della classe Color. – Sidar

+0

@Sidar Ho aggiunto un esempio. Potresti voler aggiungere del codice alla tua domanda per mostrare il tuo problema. – pmr

+1

Sono piuttosto confuso, ho pensato che è esattamente quello che sto facendo. La dichiarazione è impostata nel file cpp mentre la definizione è nell'intestazione. Com'è diverso dal tuo esempio? Non so davvero cosa mostrare di più. Questo è davvero tutto ciò che c'è da fare. – Sidar

0

È necessario qualificare il proprio operatore con lo spazio dei nomi. È una firma di funzione dichiarata nello spazio dei nomi, quindi per accedere al suo simbolo è necessario prefissarlo con lo spazio dei nomi.

Prova in questo modo:

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

mi lancia: errore: 'std :: ostream & st :: operatore << (std :: ostream &, const st :: Colore &)' avrebbe dovuto essere dichiarato all'interno 'st ' – Sidar

+0

cosa stai usando il compilatore? Funziona in Visual Studio Express 2010. Se ciò non funziona, ciò che è sicuro di lavorare è mettere il corpo del metodo nel file h all'interno del blocco namespace. – Rob

+0

GCC. Che è cosa ho fatto (guardate la mia modifica) quindi sarebbe perfetto usare lo spazio dei nomi st {} nell'intestazione stessa di nuovo, e mettere solo il sovraccarico dell'operatore lì? Mi sento come ho perso su questo informati sopra. Tutto il resto è appena trattato con st :: Color :: Etc. – Sidar