Operatorenüberladungsvererbung
-
Ah, ok Danke das wollt ich wissen

-
Hm.. also folgendes kann ich selbst im Comeau im strict Modus warnungsfrei kompilieren:
#include <iostream> using std::cout; struct Base { Base( int i ) : i ( i ) { } Base& operator=( int other ) { i = other; return *this; } Base operator*( const Base& other ) const { return Base( i * other.i ); } int i; }; struct Derived : Base { Derived( int i ) : Base( i ) { } }; int main() { Derived a( 2 ), b( 1 ); b = 2; cout << (a * b).i; }
-
Die meisten Operatoren WERDEN vererbt (wie jede normale Memberfunktion) - du mußt dir nur Gedanken machen, was sie mit dem neuen Teil der Kind-Klasse anfangen. (in lolz' Beispiel wird der operator* immer ein Base-Objekt herausgeben, also gehen eventuelle Funktionalitäten der Derived-Klasse verloren)
Die einzige (mir bekannte) Ausnahme ist der operator=. Aber den generiert der Compiler für jede neu erzeugte Klasse (wenn es ihm möglich ist) so, daß er automatisch den op= für die Basisklasse und alle neuen Membervariablen aufruft.
-
Genau, der operator= war mein Problem.
Schließlich konnte der nicht ohne Probleme einfach eine bitweise Kopie erstellen, weil ich ja einen uchar in ein bitfield umrechnen wollte
Alles klar, werd ein bisschen rumprobieren, bei nächster Gelegenheit

-
CStoll schrieb:
Die einzige (mir bekannte) Ausnahme ist der operator=. Aber den generiert der Compiler für jede neu erzeugte Klasse (wenn es ihm möglich ist) so
Was heißt "wenn es ihm möglich ist"?
Wann is es denn nicht möglich?
-
Nachfrager schrieb:
CStoll schrieb:
Die einzige (mir bekannte) Ausnahme ist der operator=. Aber den generiert der Compiler für jede neu erzeugte Klasse (wenn es ihm möglich ist) so
Was heißt "wenn es ihm möglich ist"?
Wann is es denn nicht möglich?
Wenn er bereits deklariert wurde.
-
lolz schrieb:
Nachfrager schrieb:
CStoll schrieb:
Die einzige (mir bekannte) Ausnahme ist der operator=. Aber den generiert der Compiler für jede neu erzeugte Klasse (wenn es ihm möglich ist) so
Was heißt "wenn es ihm möglich ist"?
Wann is es denn nicht möglich?
Wenn er bereits deklariert wurde.
Oder wenn Basisklassen oder member (z.b. const oder referenzen) keinen geeigneten operator= haben. Es ist nicht ganz richtig zu behaupten, dass operator= nicht vererbt werde, ohne zu sagen, was eine Memberfunktion als vererbt kennzeichnet. Das Problem beim Operator= ist, dass jede Klasse diesen implizit oder explizit deklariert, sogar dann, wenn der Compiler einen implizit deklarierten operator= nicht definieren kann (etwa wegen obiger Probleme). Diese Deklaration in jeder Klasse führt automatisch dazu, dass die geerbten Operatoren= verdeckt werden - das kann man aber z.B. durch eine using-Deklaration ändern (das wird aber im allg. keine gute Idee sein). Ein Operator= kann virtuell sein, er wird dennoch durch einen implizit deklarierten Operator= in der abgeleiteten Klasse verdeckt werden, denn die Signatur stimmt nicht überein (Wenn man nicht gerade in der Basisklasse die Signatur der abgeleiteten Klasse benutzt).
-
Nachfrager schrieb:
CStoll schrieb:
Die einzige (mir bekannte) Ausnahme ist der operator=. Aber den generiert der Compiler für jede neu erzeugte Klasse (wenn es ihm möglich ist) so
Was heißt "wenn es ihm möglich ist"?
Wann is es denn nicht möglich?
Die Default-Zuweisung (die vom Compiler erzeugt wird) ruft (afaik in dieser Reihenfolge) den Zuweisungsoperator der Basisklasse und aller Membervariablen auf (entweder über einen benutzerdefinierten op= oder über deren Default-Zuweisung - in letzter Instanz bedeutet das eine binäre Kopie). Wenn einer dieser Operatoren nicht zugänglich ist (const-Elemente, Referenzen oder Elemente mit privatisiertem operator=), streikt der Compiler.
ne0r schrieb:
Schließlich konnte der nicht ohne Probleme einfach eine bitweise Kopie erstellen, weil ich ja einen uchar in ein bitfield umrechnen wollte

Häh? Was hat das mit dem Zuweisungsoperator zu tun?
-
Also, das war so gemeint: Der überladene op= sollte das machen: ein uchar als Argument übernehmen, diesen in ein bitfield umrechnen, welches die acht Membervariablen der Basisklasse ist. In der abgeleiteten Klasse kann der Default op= das selbstverständlich nicht machen (glaube ich). Und da ist jetzt der Punkt wo ich etwas verwirrt bin: Wie wird der op= vererbt? Wird der jetzt Teil des abgeleiteten op= ? (Was ich nicht glaube, weil das ganze sonst bei mir laufen würde
) Sorry, aber momentan blick ich nicht durch...
-
Du hast in dem Fall (mindestens) drei Zuweisungsoperatoren:
base::operator=(uchar);,base::operator=(const base&);und derived::operator=(const derived&);[/c] (die beiden letzten legt der Compiler an, wenn du das nicht gemacht hast). Solange du dich in der Basisklasse befindest, kann per Überladung aufgelöst werden, welcher op= genutzt werden soll - aber der derived-Operator überdeckt seine Brüder, so daß sie nicht mehr erreichbar sind.Zur Lösung könntest du entweder die beiden base-Operatoren per using in die derived-Klasse übernehmen (keine gute Idee, weil sie nicht wissen, was sie mit dem derived-Anteil des Objekts machen sollen) oder den ersten Operator per Hand übernehmen:
class derived : public base { ... public: derived& operator=(uchar data) { base::operator=(data); // initialisiere derived-Anteile return *this; } };
-
Ah, jetzt hab ichs verstanden, danke!
Obwohl in meinem Fall die derived class nur Methoden hinzufügen würde.
Ach ja:

-
ne0r schrieb:
Obwohl in meinem Fall die derived class nur Methoden hinzufügen würde.
Ich korrigiere: DU hast nur Methoden hinzugefügt. Der Compiler legt für jede Klasse automatisch einen Copy-Ctor, operator= und Dtor (und in den meisten Fällen auch einen Default-Ctor) an, unabhängig von dem, was du machst.
Edit:
ne0r schrieb:
guckst du hier
(in Kurzform: Wer die Syntax verstanden hat, kann damit wunderschöne mathematische Formeln darstellen)
-
Sinnvoller als die Überladung des Zuweisungsoperators dürfte die entsprechende Definition von Konstruktoren sein.
-
Üblicherweise denke ich das auch, nur wenn ich mit der Klasse (die im Übrigen eh vollkommener Schwachfug ist/war) mathematische Operationen durchführen will, stoße ich mit Konstruktoren schnell an meine Grenzen

-
ne0r schrieb:
Üblicherweise denke ich das auch, nur wenn ich mit der Klasse (die im Übrigen eh vollkommener Schwachfug ist/war) mathematische Operationen durchführen will, stoße ich mit Konstruktoren schnell an meine Grenzen

Für Klassen, die Operanden für mathematische Operationen sein sollen, ist Polymorphie ohnehin selten nützlich oder sinnvoll. Und damit entfällt dann in der Regel auch der Bedarf für öffentliche Vererbung eines Interfaces.