2015-06-24 20 views
5

Ich verstehe nicht ganz, warum für eine Zuordnung eine abgeleitete Klasse nicht den entsprechenden Betreiber der Basisklasse aufrufen, wenn ihre eigene existiert nicht. Sehen Sie sich den Code an:C++ Zuweisungsoperator in abgeleiteten Klasse

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

Wie es ist der Code kompiliert nicht. Natürlich, wenn ich einen "Operator =" für B definiere, der identisch ist mit dem für A, funktioniert alles, aber warum wird der B "operator =" nicht standardmäßig aufgerufen, wenn der in der abgeleiteten Klasse nicht definiert ist? Könnten Sie mir helfen, etwas Licht in dieses Thema zu bringen?

Der GCC-Compiler sagt ../src/tito.cpp:40:4: Fehler: keine brauchbare überladene '=' pp = 0,0; ~~^~~~ ../src/tito.cpp:28:7: Hinweis: Kandidaten-Funktion (die implizite Kopierzuweisungsoperator) nicht durchführbar: keine Konvertierung bekannt aus ‚double‘ auf ‚const B‘ für erste Argument Klasse B: öffentlich A { ^ 1 Fehler generiert.

Können Sie uns erklären, warum es nicht funktioniert?

Antwort

8

Wenn Sie keine Kopie Zuweisungsoperator deklarieren, wird der Compiler für Sie erklären. So Ihre Klasse Bwirklich wie folgt aussieht:

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

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

Die implizite Kopierzuweisungsoperator versteckt der A::operator=(double), die Sie geschrieben haben, so dass er der einzige Kandidat ist, dass Namen-Suche finden. Natürlich ist es kein praktikabler Kandidat, da double nicht zu B umwandelbar ist, daher der Fehler.

den A::operator=(double) Operator verwenden, müssen Sie es explizit in den Gültigkeitsbereich bringen:

using A::operator=; 

Aber dann gehen Sie nicht der B Teil zu zuweisen. Also würde es besser sein, zu sein explizit:

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

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

    return *this; 
} 
+1

Ja, der Hauptgrund ist das Mutter 'Operator =' nicht das Kind Teil nicht zuweisen, so implizit mit es easilly gebrochene Objekte erstellen können. – StenSoft

+0

Vielen Dank für den sehr nützlichen Kommentar !! – Max

2

Der Kopierzuweisungsoperator der abgeleiteten Klasse, die implizit vom Compiler deklariert wird versteckt Zuweisungsoperator der Basisklasse. Verwenden Sie in der abgeleiteten Klasse die folgenden Weise

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

Einen anderen Ansatz Erklärung wird den virtuellen Zuweisungsoperator in der abgeleiteten Klasse

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

In diesem Fall neu deklarieren Sie den Polymorphismus verwenden können. Zum Beispiel

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

Die Programmausgabe ist

10 10 
20 20 
Verwandte Themen