unreine, reine virtuelle Funktion
-
Hallo, ich bin gerade dabei ein bischen C++ zu lernen als ich über eine Aufgabe gestolpert bin. Ich hoffe ihr könnt mir helfen. Mein Problem ist die invariant vererbt Funktion. Sehe ich das richtig das damit eine reine vituelle Funktion gemeint ist?
Definieren Sie eine abstrakte Klasse – was ist in der Klassendefinition kenntlich zu machen – die eine unreine virtuelle Funktion und eine Funktion enthält, die invariant vererbt wird?
Meine Lösung
class Abstrakt {
public:
virtual void lesen(); // unreine virtuelle Funktion
virtual void drucken() = 0; // reine virtuelle Funktion bzw. invariant vererbt
};
-
Abstrakte Klasse:
class MyInterface { virtual void PureVirtualMethod() = 0; }rya.
-
ühm, ja, genau.
Eine abstrakte Klasse... entnehme ich deiner antwort Richtig das ich bei meiner Lösung das public: raus machen und das ; am ende der Klasse entfernen soll?
Dann bliebe nur noch die Frage offen ist eine invariant vererbt Funktion das gleiche wie eine reine vituelle Funktion?
-
kronosa schrieb:
Eine abstrakte Klasse... entnehme ich deiner antwort Richtig das ich bei meiner Lösung das public: raus machen und das ; am ende der Klasse entfernen soll?
Dann bliebe nur noch die Frage offen ist eine invariant vererbt Funktion das gleiche wie eine reine vituelle Funktion?
Nö. Deines passt schon.
Invariant vererbt Funktion hätte ich jetzt noch nie gehört, aber wenn ich es richtig verstehe, ist dein Beispiel richtig. Da der eigentliche Code, der die Funktion ausführt nicht in der Klasse selbst definiert ist. Somit ist die Invariante bei einer abeleiteten Klasse.
-
kronosa schrieb:
Hallo, ich bin gerade dabei ein bischen C++ zu lernen als ich über eine Aufgabe gestolpert bin. Ich hoffe ihr könnt mir helfen. Mein Problem ist die invariant vererbt Funktion. Sehe ich das richtig das damit eine reine vituelle Funktion gemeint ist?
Nein, invariante Funktionen sind eben invariant, also über die komplette Vererbungshierarchie unveränderlich. Das ist das genaue Gegenteil von (rein) virtuellen Funktionen, die sich ja polymorph ändern können.
kronosa schrieb:
Definieren Sie eine abstrakte Klasse – was ist in der Klassendefinition kenntlich zu machen – die eine unreine virtuelle Funktion und eine Funktion enthält, die invariant vererbt wird?
Das würde dann z.B. so aussehen:
class SomeClass { virtual void pureVirtuel() = 0; //rein virtuelle Funktion virtual void justVirtual(){/*do something here*/} //virtuelle Funktion void invariant(){/*do something here*/}//invariante Funktion };Die invarianten Funktionen werden also einfach von erbenden Funktionen aus der Basisklasse übernommenm und dürfen nicht reimplementiert werden.
Oder genauer:- Bei rein virtuellen Funktionen wird nur das Interface einer Funktion vererbt (also wie die Funktion aufgerufen wird).
- Bei virtuellen Funktionen wird das Interface und eine lose gekoppelte Standard-Implementierung vererbt. Die Standardimplementierung darf aber später von erbenden Funktionen geändert werden.
- Bei invarianten Funktionen wird die Implementierung fest gekoppelt an das Interface vererbt. Diese darf von abgeleiteten Klassen nicht geändert werden. Deher ist sie eben invariant.
-
Wow, super Erklärung Tachyon, danke. Das werd ich mir jetzt genau so als Beispiel aufschreiben. Die drei Merksätze sind gut.
-
Was Tachyon nicht erwähnt hat:
Die invarianten Funktionen können von abgeleiteten Klassen durchaus überschrieben werden, so dass ein Aufruf über einen Pointer/Referenz auf die abgeleitete Klasse auch die Funktion in der abgeleiteten Klasse aufruft. Ein Aufruf über den Basisklassenpointer wird aber immer die Basisklassenfunktion aufrufen, da bei nichtvirtuellen Funktionen der statische Typ des Objekts (also des Pointers) entscheidend ist.
Ich verdeutliche das mal an nem Beispiel:struct Base { void invariantFunc() {cout << "base:invariant" << endl;} virtual void virtualFunc() {cout << "base::virtual" << endl;} }; struct Derived : public Base { void invariantFunc() {cout << "derived:invariant" << endl;} //überschreibt base::invariantFunc virtual void virtualFunc() {cout << "derived::virtual" << endl;} }; int main() { Base b; Derived d; Base* pb1 = &b; //statischer und dynamischer Typ ist Base Base* pb2 = &d; //statischer Typ ist Base, dynamischer Typ Derived Derived* pd = &d; //statischer und dynamischer Typ ist Derived pb1->virtualFunc(); //base::virtual , dynamischer Typ zählt pb1->invariantFunc(); //base::invariant , statischer Typ zählt pb2->virtualFunc(); //derived::virtual , dynamischer Typ zählt pb2->invariantFunc(); //base::invariant , statischer Typ zählt pd->virtualFunc(); //derived::virtual , dynamischer Typ zählt pd->invariantFunc(); //derived::invariant , statischer Typ zählt }Alle Klarheiten beseitigt?

-
pumuckl schrieb:
Was Tachyon nicht erwähnt hat:[...]
Ich habs bewusst weggelassen, weil man das eigentlich tunlichst vermeiden sollte und es nicht zur Beantwortung der Frage beiträgt. Im Normalfall ist das ein Designfehler, der einem die "Is-A"-Beziehung zerschrottet, und Verhalten auslöst, dass man nicht erwartet hätte. Mal davon abgesehen, ist das im Kontext der Aufgabe auch völliger Unsinn. Wenn die abgeleitete Klasse eine invariante Funktion wirklich anders implementieren muss, dann ist sie wohl nicht so wirklich invariant, oder?

Genaugenommen ist das sogar eine Sache, die man nie benötigt. Da man eh immer Qualifizieren muss, kann man der Funktion in der abgeleiteten Klasse ebensogut einen anderen Namen geben.pumuckl schrieb:
[...]Alle Klarheiten beseitigt?

Das ist allerdings wahr...