6 Stimmen

Unter-Klassen, Überladen des Zuweisungsoperators?

Wenn ich die unten stehenden Klassen habe:

class TestA
{
    public:
        const TestA &operator=(const int A){return *this;}
};

class TestB : public TestA
{
    public:
        //Vererbung?
};

Die Frage setzt voraus, dass sowohl die Klasse TestA als auch die Klasse TestB genau den gleichen Inhalt in Bezug auf Variablen haben: Wird der Zuweisungsoperator (oder ein anderer Operator) vererbt?

Ist folgendes gültig?

class TestB : public TestA
{
    public:
        using TestA::operator=;
        //Vererbung?
};

Wenn es gültig ist, würde es einen Unterschied machen?

3voto

iammilind Punkte 64857

Zuweisungsoperatoren werden standardmäßig von der abgeleiteten Klasse ausgeblendet (da der Compiler immer ein T& operator = () für jede Klasse T generiert, wenn nicht anders angegeben). Dadurch wird der geerbte operator = nicht nutzbar.

Ja, wenn Sie sie mit dem using-Schlüsselwort angeben, werden sie verwendbar. Demo. Daher macht Ihr Codeausschnitt Sinn.

public: using TestA::operator=;

3voto

Cheers and hth. - Alf Punkte 138555

Der Beispielcode der Frage zum Zeitpunkt des Verfassens:

class TestA
{
    public:
        const TestA &operator=(const int A){return *this;}
};

class TestB : public TestA
{
    public:
        //Vererbung?
};

Frage 1: "Wird der Zuweisungsoperator (oder ein anderer Operator) vererbt?"

Ja, natürlich. Die einzigen Elementfunktionen, die nicht in C++98 vererbt werden, sind Konstruktoren. Die Implementierungen der Basisklasse werden jedoch standardmäßig vom automatisch generierten Kopiezuweisungsoperator verborgen. Beispiel:

#include <iostream>
using namespace std;

class TestA
{
    public:
        TestA const& operator=( int const )
        {
            cout << "TestA = int" << endl;
            return *this;
        }
};

class TestB : public TestA
{
    public:
        // Automatisch generierter Kopiezuweisungsoperator.
};

int main()
{
    TestB   o;

    cout << "Aufruf des automatisch generierten Kopiezuweisungsoperators:" << endl;
    cout << "(sollte hier nichts stehen ->) ";  o = TestB();
    cout << endl;
    cout << endl;

    cout << "Aufruf des Zuweisungsoperators der Basisklasse:" << endl;
    // o = 42;     // kompiliert nicht, da er verborgen ist.
    cout << "(sollte hier eine Ausgabe stehen ->) ";  o.TestA::operator=( 42 );   // OK.
    cout << endl;
}

Angesichts aller bisherigen Antworten, die Verbargenes und Vererbung verwechselt haben, und um hier nur die Terminologie zu klären, sagt N3290 (welches dem C++11-Standard identisch ist):

N3290 §10/2:
"Vererbene Elemente können in Ausdrücken auf die gleiche Weise wie andere Elemente der abgeleiteten Klasse verwiesen werden, es sei denn, ihre Namen sind verborgen oder mehrdeutig"

In dem obigen Beispielcode ist TestA::operator= verborgen, siehe jedoch die Antwort zu Frage 3.

Frage 2: Ist das Folgende gültig?

Die Frage bezieht sich auf die Verwendung von using in der abgeleiteten Klasse, so wie:

class TestB : public TestA
{
    public:
        using TestA::operator=;
        //Vererbung?
};

Ja, das ist gültig.

In C++98 wäre dies nicht für einen Konstruktor gültig, da Konstruktoren nicht vererbt werden.

Frage 3: Wenn es gültig ist, macht es einen Unterschied?

Ja, es ermöglicht den direkten Zugriff auf den Zuweisungsoperator der Basisklasse in der abgeleiteten Klasse.

Beispielsweise können Sie dann das Auskommentieren im obigen Beispiel entfernen,

// o = 42;     // kompiliert nicht, da er verborgen ist.

und es wird immer noch kompilieren,

o = 42;        // kompiliert einwandfrei mit "using".

Prost & hth.,

2voto

RoundPi Punkte 5549

Ich habe einige verwandte Antworten im C++ 11-Standard gefunden:

12.8 Kopieren und Verschieben von Klassenobjekten

Weil ein Kopier- bzw. Verschiebezuweisungsoperator für eine Klasse implizit deklariert wird, wenn er nicht vom Benutzer deklariert wird, wird ein Kopier- bzw. Verschiebezuweisungsoperator einer Basisklasse immer vom entsprechenden Zuweisungsoperator einer abgeleiteten Klasse versteckt (13.5.3). Eine Verwendungsdeklaration (7.3.3), die einen Zuweisungsoperator mit einem Parameter in eine abgeleitete Klasse einbringt, der dem eines Kopier- bzw. Verschiebezuweisungsoperators für die abgeleitete Klasse entsprechen könnte, wird nicht als explizite Deklaration eines solchen Operators angesehen und unterdrückt nicht die implizite Deklaration des Operators der abgeleiteten Klasse; der durch die Verwendungsdeklaration eingeführte Operator wird vom implizit deklarierten Operator in der abgeleiteten Klasse versteckt.

0voto

Tony The Lion Punkte 59566

Zuweisungsoperator wird nicht von abgeleitetem geerbt. Wenn Sie Ihren überladenen Zuweisungsoperator in Ihrem abgeleiteten Typ aus Ihrer Basis verwenden, können Sie auf Slicing stoßen: sizeof(base) != sizeof(derived)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X