2012-02-06 23 views
14

Hay este código:Asignación herencia operador

#include <iostream> 

class Base { 
public: 
    Base(){ 
     std::cout << "Constructor base" << std::endl; 
    } 
    ~Base(){ 
     std::cout << "Destructor base" << std::endl; 
    } 
    Base& operator=(const Base& a){ 
     std::cout << "Assignment base" << std::endl; 
    } 
}; 

class Derived : public Base{ 
public: 

}; 

int main (int argc, char **argv) { 
    Derived p; 
    Derived p2; 
    p2 = p; 
    return 0; 
} 

La salida después de la compilación por g ++ 4.6:

Constructor base 
Constructor base 
Assignment base 
Destructor base 
Destructor base 

¿Por qué operador de asignación de clase base se llama Altough se dice que operador de asignación no es ¿heredado?

+1

posible duplicado de [Problema con la herencia del operador = en C++] (http://stackoverflow.com/questions/3882186/trouble-with-herititance-of-operator-in-c) –

Respuesta

13

Usted no tiene un defecto

Derived& operator=(const Base& a); 

en su clase Derived.

Un operador de asignación por defecto, sin embargo, se crea:

Derived& operator=(const Derived& a); 

y esto llama al operador de asignación de Base. Por lo tanto, no se trata de heredar el operador de asignación, sino de llamarlo a través del operador generado por defecto en su clase derivada.

+9

operator = es heredar de la clase basada como cito del estándar 98 C++ "Las funciones del operador son heredado de la misma manera que otras funciones de la clase base ". Simplemente ha sido ocultado por operator = creado implícitamente para la clase Derived. – Gob00st

+1

"Ha sido oculto por operador creado implícitamente = para clase Derivada". Al igual que si la clase base tiene func nulo (int) y la clase derivada tiene func nulo (doble), la función de clase base void func (int) está oculta. En líneas similares, el operador de clase base = está oculto por el operador de clase derivado =. – Sandeep

+0

... y para ser claros, dado que la base 'operator =' solo se ha ocultado, se puede mostrar en la clase derivada con 'using Base :: operator =;' y boom: allí está, heredado. Consulte: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

-1

Esto se debe a que el operador de asignación predeterminado creado llama a su operador de asignación básica, es decir, no se hereda, pero se llama como parte del operador de asignación predeterminado.

+0

El operador de asignación ** es ** heredado de la base. Simplemente está oculto por el generado por el compilador en la clase derivada. El uso de 'using Base :: operator =;' probaría esto al mostrar la implementación base y hacerla disponible a través de la clase derivada. Ver: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

31

En realidad, lo que se llama es el operator = implícitamente definido para Derived. La definición proporcionada por el compilador a su vez llama al operator = para el Base y ve la salida correspondiente. Lo mismo ocurre con el constructor y el destructor. Al salir de ella al compilador para definir operator =, lo define de la siguiente manera:

Derived& operator = (const Derived& rhs) 
{ 
    Base1::operator =(rhs); 
    ... 
    Basen::operator =(rhs); 
    member1 = rhs.member1; 
    ... 
    membern = rhs.membern; 
} 

donde Base1,...,Basen son las bases de la clase (con el fin de ser especificados en la lista de la herencia) y member1, ..., membern son los miembros del Derivado (sin contar los miembros que fueron heredados) en el orden en que los declaraste en la definición de la clase.

-1

El operador de asignación no se hereda. Heredar ese operador le permitiría asignar un Base a un Derived; sin embargo, Base b; p = a; no compilará (con razón).

Lo que sucede es que el compilador genera un operator=, ya que no ha definido uno personalizado para Derived. El autogenerado operator= llamará a los operadores de asignación de todas las clases base y todos los miembros. En ese aspecto, es muy parecido a los constructores/destructores, que también llaman a la función respectiva en todas las Bases/miembros.

+1

El operador de asignación ** es ** heredado de la base. Simplemente está oculto por el generado por el compilador en la clase derivada. El uso de 'using Base :: operator =;' probaría esto al mostrar la implementación base y hacerla disponible a través de la clase derivada. Ver: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

7

dice Estándar (12.8):

un operador de asignación se llevará a cabo mediante una función miembro no estática con exactamente un parámetro. Como el usuario (12.8) declara implícitamente una operación de copia operador = si el usuario no declara (12.8), un operador de asignación de clase base siempre está oculto por el operador de asignación de copias de la clase derivada.

y luego operador de asignación de derivado llame a su base de

El operador de asignación de copia/movimiento definido implícitamente-para un no-unión clase X realiza miembro por miembro contra copias/mover asignación de sus subobjetos. Las clases base directas de X se asignan primero, en el orden de su declaración en la base-especificador-lista, y luego se asignan los datos de datos no-estáticos inmediatos, en el orden en que se declararon en la definición de clase.

17

También puede utilizar el "uso":

class Derived : public Base{ 
public: 
    using Base::operator=; 
}; 

http://en.cppreference.com/w/cpp/language/using_declaration

leí este post varias veces antes de que alguien me ayudó con esto.

+2

Finalmente, alguien lo dijo. +1. Ver también: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

Cuestiones relacionadas