2009-12-02 8 views
7

Me he encontrado con un problema que no entiendo y esperaba que alguien aquí pudiera proporcionar alguna información. El código simplificada es la siguiente (código original fue una implementación cola personalizada/cola-iterador):Operador de asignación predeterminado en la clase interna con miembros de referencia

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

Esto, cuando se compila, me da el siguiente error:

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 

puedo ir alrededor de este usando dos variables C separadas, ya que se supone que son objetos independientes 'C', pero esto solo oculta el problema (todavía no entiendo por qué no puedo hacer esto).

Creo que la razón es que la referencia no se puede copiar, pero no entiendo por qué. ¿Debo proporcionar mi propio operador de asignación y copiador?

Respuesta

13

Este problema no tiene nada que ver con las clases internas. En C++, simplemente no puede (re) asignar referencias; deben inicializarse cuando se definan.

Un ejemplo más sencillo es:

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, por supuesto que estás en lo cierto, no puedo creer que me haya olvidado de la explicación obvia. Debería haber tomado más café por la mañana: D – laura

+2

+1. Me parece que el uso habitual de "atar" en lugar de "asignar" cuando se habla de referencias me ayuda a cometer este error. –

+0

ahora, voy a reasignar una referencia y por supuesto compilará: int a = 3; int b = 4; int & ref = a; ref = b ;. Por lo tanto, es posible reasignar una referencia. – friko

6

Una referencia no se puede cambiar después de recibir su valor inicial. Esto significa que es imposible escribir un operador de asignación que cambie el valor de un miembro de referencia. Si necesita hacer esto, use un puntero en lugar de una referencia.

+0

En realidad es posible. Mira mi comentario a continuación para más detalles. – rmn

0

C++ no tiene "clases internas", sólo declaraciones de clases anidadas. Las "clases internas" son un lenguaje Java que no creo que se encuentren en otros lenguajes principales. En Java, las clases internas son especiales porque contienen una referencia inmutable implícita a un objeto del tipo que lo contiene. Para lograr el equivalente a las declaraciones anidadas de C++ en Java, se requiere el uso de clases internas estáticas; las clases internas estáticas no contienen una referencia a un objeto del tipo declarante.

3

En realidad, hay una solución para esto. Puede implement operator= in terms of copy construction, y funcionará :) Es una técnica muy capaz para tales casos. Suponiendo que quieres apoyar la tarea.

+1

Llamar a un destructor en un operador de asignación es un muy mal hábito de programación. – Sjoerd

+1

En primer lugar, gracias por su respuesta, había llegado a esta solución por mi cuenta, pero omití la verificación de autoasignación y la llamada al destructor explícito. Usted nota que no recomienda usarlo (y estoy de acuerdo con su razonamiento), dadas estas desventajas, ¿existe una implementación preferida? – dukedave

Cuestiones relacionadas