2009-12-02 22 views
7

Ho riscontrato un problema che non capisco e speravo che qualcuno qui potesse fornire alcune informazioni. Il codice semplificato è il seguente (codice originale era un'implementazione coda di custom/coda iterator):Operatore di assegnazione predefinito nella classe interna con gli elementi di riferimento

class B 
{ 
public: 
    B() {}; 
    class C 
    { 
    public: 
     int get(); 
     C(B&b) : b(b){}; 
    private: 
     B& b; 
    }; 
public: 
    C get_c() { return C(*this); } 
}; 

int main() 
{ 
    B b; 
    B::C c = b.get_c(); 


    c = b.get_c(); 
    return EXIT_SUCCESS; 
} 

Questo, quando compilato, mi dà il seguente errore:

foo.cpp: In member function 'B::C& B::C::operator=(const B::C&)': 
foo.cpp:46: error: non-static reference member 'B& B::C::b', can't use default assignment operator 
foo.cpp: In function 'int main()': 
foo.cpp:63: note: synthesized method 'B::C& B::C::operator=(const B::C&)' first required here 

posso andare in giro questo utilizzando due variabili C separate, in quanto si suppone che siano oggetti "C" indipendenti, ma questo nasconde solo il problema (non capisco ancora perché non posso farlo).

Penso che il motivo sia che il riferimento non può essere copiato, ma non capisco perché. Devo fornire il mio operatore di assegnazione e copiare il costruttore?

risposta

13

Questo problema non ha nulla a che fare con le classi interne. In C++ non puoi (ri) assegnare riferimenti - devono essere inizializzati quando definiti.

Un esempio più semplice è:

class B 
{ 
public: 
    B(int& i) : ir(i) {}; 

    int& ir; 
}; 


int main() 
{ 
    int i; 
    B b(i);  // Constructor - OK 

    int j; 
    B bb = B(j); // Copy constructor - OK 

    bb = b;  // Assignment - Error 
    return 0; 
} 
+0

Bah, certo che hai ragione, non posso credere di aver perso l'ovvia spiegazione. Dovrebbe avere più caffè al mattino: D – laura

+2

+1. Trovo che usare abitualmente "bind" piuttosto che "assegnare" quando si parla di riferimenti mi aiuti a fare questo errore. –

+0

ora, ho intenzione di riassegnare un riferimento e, naturalmente, verrà compilato: int a = 3; int b = 4; int & ref = a; ref = b ;. Quindi è possibile riassegnare un riferimento. – friko

6

Un riferimento non può essere modificato dopo aver ricevuto il suo valore iniziale. Ciò significa che è impossibile scrivere un operatore di assegnazione che modifichi il valore di un membro di riferimento. Se è necessario, utilizzare un puntatore anziché un riferimento.

+0

In realtà è possibile. Controlla il mio commento qui sotto per i dettagli. – rmn

0

C++ non ha "classi interne", solo dichiarazioni di classe nidificate. Le "classi interne" sono un Java-ismo che non credo si trovi in ​​altre lingue tradizionali. In Java, le classi interne sono speciali perché contengono un riferimento immutabile implicito a un oggetto del tipo contenente. Per ottenere l'equivalente delle dichiarazioni annidate in C++ in Java è necessario l'uso di classi interne statiche; le classi interne statiche non contengono un riferimento a un oggetto del tipo dichiarante.

3

In realtà, c'è una soluzione a questo. È possibile implement operator= in terms of copy construction e funzionerà :) È una tecnica molto efficace per questi casi. Supponendo che tu voglia sostenere l'incarico.

+1

Chiamare un distruttore in un operatore di assegnazione è una pessima abitudine di programmazione. – Sjoerd

+1

Innanzitutto grazie per la tua risposta, avevo raggiunto questa soluzione da solo, ma ho omesso il controllo di autoassegnazione e la chiamata al distruttore esplicita. Nota che non è consigliabile utilizzarlo (e sono d'accordo con il tuo ragionamento), dato questi svantaggi c'è un'implementazione preferita? – dukedave

Problemi correlati