2015-06-24 34 views
5

Non capisco perché per un compito una classe derivata non chiami l'operatore corrispondente della classe base, se la sua non esiste. Guarda il codice:Operatore di assegnazione C++ nella classe derivata

#include <iostream> 
using namespace std; 

class A{ 
protected: 
    void myWrite(){ 
    cout << " Base " <<endl; 
    } 
public: 
    double x,y; 
    A(): x{0},y{0}{}; 
    virtual A & operator=(double g){x=g;y=g;return *this;} 
    virtual ~A(){}; 
    virtual void doneit(){myWrite();} 
}; 


class B: public A{ 
protected: 
public: 
    B():A(){}; 
    virtual ~B(){}; 
    virtual void doneit(){myWrite();} 
}; 

int main() { 
    A jj; 
    B pp; 

    pp=0.0; 
    return 0; 
} 

Come è il codice non viene compilato. Naturalmente se definisco un "operator =" per B identico a quello per A, tutto funziona, ma perché B "operator =" non viene chiamato di default se quello nella classe derivata non è definito ?? Potresti aiutare a far luce su questo problema?

Il compilatore gcc dice ../src/tito.cpp:40:4: errore: non valido sovraccarico '=' pp = 0,0; ~~^~~~ ../src/tito.cpp:28:7: nota: la funzione candidata (l'operatore di assegnazione implicita della copia) non è valida: nessuna conversione nota da "double" a "const B" per 1o argomento classe B: pubblico A { ^ 1 errore generato.

Puoi spiegare perché non funziona?

risposta

8

Se non si dichiara un operatore di assegnazione copia, il compilatore ne dichiara uno. Quindi la classe Bdavvero assomiglia:

class B : public A { 
public: 
    // explicit 
    B(); 
    virtual ~B(); 
    virtual void doneit(); 

    // implicit 
    B(const B&); 
    B& operator=(const B&); 
}; 

L'operatore di assegnazione copia implicita pelli la A::operator=(double) che hai scritto, quindi è l'unico candidato che il nome di ricerca troverà. Certo, non è un candidato praticabile, dal momento che double non è convertibile in B, quindi l'errore.

di utilizzare l'operatore A::operator=(double), è necessario portare in modo esplicito in ambito:

using A::operator=; 

Ma allora non sta andando ad essere l'assegnazione di qualsiasi parte B. Quindi sarebbe meglio essere più esplicito:

B& operator=(double g) { 
    // B stuff here 

    // A stuff 
    A::operator=(g); 

    return *this; 
} 
+1

Sì, la ragione principale è 'operatore di quel genitore =' non assegna parte del bambino in modo implicito ad usarlo può easilly creare oggetti rotti. – StenSoft

+0

Grazie per il commento molto utile !! – Max

2

La copia assegnazione operatore della classe derivata che è implicitamente dichiarata dal compilatore nasconde operatori di assegnazione della classe di base. Utilizzare utilizzando dichiarazione nella classe derivata seguente modo

class B: public A{ 
protected: 
public: 
    using A::operator =;  
    B():A(){}; 
    virtual ~B(){}; 
    virtual void doneit(){myWrite();} 
}; 

Un altro approccio è quello di ridichiarare l'operatore di assegnamento virtuale nella classe derivata

B & operator=(double g) { A::operator =(g) ;return *this;} 

In questo caso è possibile utilizzare il polimorfismo. Per esempio

#include <iostream> 

class A 
{ 
public: 
    double x,y; 
    A(): x{0}, y{0} {} 
    virtual A & operator =(double g){ x = g; y = g; return *this; } 
    virtual ~A(){} 
}; 


class B: public A 
{ 
public: 
    B() : A(){} 
    virtual B & operator =(double g) override { A::operator =(2 * g) ; return *this; } 
    virtual ~B(){} 
}; 

int main() 
{ 
    A a; 
    B b; 

    A *p = &a; 

    *p = 10; 

    std::cout << p->x << ' ' << p->y << std::endl; 

    p = &b; 

    *p = 10; 

    std::cout << p->x << ' ' << p->y << std::endl; 

    return 0; 
} 

L'output del programma è

10 10 
20 20 
Problemi correlati