2012-02-06 31 views
14

C'è questo codice:Assegnazione operatore eredità

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

L'uscita dopo la compilazione da g ++ 4.6:

Constructor base 
Constructor base 
Assignment base 
Destructor base 
Destructor base 

Perché operatore di assegnazione della classe di base è chiamato benche si dice che operatore di assegnazione non è ereditato?

+1

possibile duplicato di [Problemi con l'ereditarietà dell'operatore = in C++] (http://stackoverflow.com/questions/3882186/trouble-with-inheritance-of-operator-in-c) –

risposta

13

Non è un default

Derived& operator=(const Base& a); 

nella classe Derived.

Un operatore di assegnazione di default, tuttavia, viene creato:

Derived& operator=(const Derived& a); 

e questo chiama l'operatore di assegnazione da Base. Quindi non si tratta di ereditare l'operatore di assegnazione, ma di chiamarlo tramite l'operatore generato di default nella classe derivata.

+9

operator = è ereditato dalla classe base come cito da 98 C++ standard "Le funzioni dell'operatore sono ereditato nello stesso modo delle altre funzioni di classe base. " È stato appena nascosto dall'operatore implicitamente creato = per la classe derivata. – Gob00st

+1

"È stato appena nascosto dall'operatore implicitamente creato = per la classe derivata". Proprio come se la classe base ha void func (int) e la classe derivata ha void func (double), la funzione di base class void func (int) è nascosta. Su linee simili l'operatore di classe base = è nascosto dall'operatore di classe derivata =. – Sandeep

+0

... e per essere chiari, poiché la base 'operator =' è stata nascosta, può essere nascosta nella classe derivata usando 'Base :: operator =;' e boom: eccolo, ereditato. Vedi: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

-1

Questo perché l'operatore di assegnazione predefinito ha creato chiamate come operatore di assegnazione di base, ovvero non è ereditato ma viene ancora chiamato come parte dell'operatore di assegnazione predefinito.

+0

L'operatore di assegnazione ** è ** ereditato dalla base. È solo nascosto da quello generato dal compilatore nella classe derivata. L'uso di 'using Base :: operator =;' proverebbe questo scoprendo l'implementazione di base e rendendola disponibile tramite la classe derivata. Vedi: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

31

In realtà, ciò che viene chiamato è lo operator = implicitamente definito per Derived. La definizione fornita dal compilatore a sua volta chiama operator = per Base e viene visualizzato l'output corrispondente. Lo stesso è con il costruttore e il distruttore. Quando si lascia al compilatore di definire operator =, definisce come segue:

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

dove Base1,...,Basen sono le basi della classe (in ordine di specificarli nella lista eredità) e member1, ..., membern sono i membri di Derived (senza contare i membri che sono stati ereditati) nell'ordine in cui li hai dichiarati nella definizione della classe.

-1

L'operatore di assegnazione non è effettivamente ereditato. Ereditare quell'operatore ti consentirebbe di assegnare un Base a un Derived, tuttavia Base b; p = a; non sarà (giustamente) riuscito a compilare.

Quello che succede è che il compilatore genera uno operator=, poiché non è stato definito uno personalizzato per Derived. Il numero operator= generato automaticamente chiamerà gli operatori di assegnazione di tutte le classi di base e di tutti i membri. In questo aspetto è molto simile a costruttori/distruttori, che chiamano anche la rispettiva funzione su tutte le Basi/membri.

+1

L'operatore di assegnazione ** è ** ereditato dalla base. È solo nascosto da quello generato dal compilatore nella classe derivata. L'uso di 'using Base :: operator =;' proverebbe questo scoprendo l'implementazione di base e rendendola disponibile tramite la classe derivata. Vedi: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

7

dice standard (12.8):

un operatore di assegnazione è attuato da una funzione non statica membro con esattamente un parametro. Poiché un assegnamento di copia operator operator = è implicitamente dichiarato per una classe se non dichiarato dall'utente (12.8), un operatore di assegnazione di classe base è sempre nascosto dall'operatore di assegnazione copia della classe derivata.

e poi l'assegnazione operatore del derivato chiamare la vostra base

L'operatore di assegnazione di copia/spostamento implicitamente definito per un non-union classe X esegue membro a membro della copia/spostare l'assegnazione dei suoi oggetti secondari. Le classi di base dirette di X vengono assegnate per prime, nell'ordine della loro dichiarazione nell'elenco di specificatori di base, e quindi vengono assegnati immediatamente i membri di dati non statici di X, nell'ordine in cui sono stati dichiarati nella definizione della classe.

17

È inoltre possibile utilizzare "usando":

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

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

ho letto questo post più volte prima che qualcuno mi ha aiutato con questo.

+2

Infine, qualcuno lo ha detto. +1. Vedi anche: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

Problemi correlati