titel
-
nachrichtentext
-
In deinen ersten 4 Zeilen verstehe ich dein Problem nicht so ganz, stimmt doch.
Nun zu deinen Fragen:
zu 1.:
Nicht wirlich. Virtuelle Methoden bewirken letztendlich nur, dass im Falle von Vererbung nicht die Funktion der Basisklasse, sondern die richtige Funktion der abgeleiteten Klasse aufgerufen wird.
Bsp:#include <iostream> class Base { public: void print() { std::cout << "Base!"; } }; class Extended : public Base { public: void print() { std::cout << "Extended!"; } }; int main () { Base* b = new Extended; b->print(); }
Gibt "Base!" aus.
Wohingegen:
#include <iostream> class Base { public: virtual void print() { std::cout << "Base!"; } }; class Extended : public Base { public: void print() { std::cout << "Extended!"; } }; int main () { Base* b = new Extended; b->print(); }
Zu "Extended!" auf dem Bildschirm führt.
Es gilt zu beachten, dass dies nur bei Zeigern und Referenzen klappt. Hätte ich meine "b" als Objekt von "Base" erzeugt, hätte auch die virtuelle Funktion nichts geholfen.Zu 2.:
In "dieser" Klasse? Welche Klasse meinst du? Aber ja: Virtuelle Methoden können in jeder Klasse definiert werden.Zu 3.:
Jap. Das hat zur Folge, dass alle davon abgeleiteten Klasse diese Methode implementieren müssen, vorausgesetzt, sie wollen nicht selbst ebenfalls abstrakt sein.zu 4.:
Nein, das führt zu einem Compilerfehler. Die Syntax für abstrakte Klassen / Methoden lautet:virtual type abstract_operation(/* params */) = 0;
zu 5.:
Selbst wenn solche Membervariablen vorhanden sind, wird immer noch eine Standardversion erzeugt. Du hast jedoch vollkommen Recht: Sobald Zeiger (und damit häufig dynamisch allozierter Speicher) ins Spiel kommt, ist es ratsam, die von dir genannten Methoden selbst zu definieren.zu 6.:
Was für 5. gilt, gilt auch hier.zu 7.:
siehe 5.zu 8.:
Auch hier erfolgen die Aufrufe von oben nach unten bei der Konstruktion und von unten nach oben bei der Destruktion eines Objekts. Dementsprechend muss hier nichts weiter gemacht werden, wie du schon vermutest. Ein häufig gemachter Fehler ist es jedoch, einen nicht-virtuellen Destruktor bei Basisklassen zu haben. Dies führt zur unvollständigen Beseitigung von Objekten und kann ziemlich ungemütlich werden. Deshalb gilt bei Vererbung immer: Destruktor virtuell!Zu deinem "Beispiel" (wieso schreibst du nicht einfach Hausaufgabe? :D):
Vorab, dein Kollege redet Quark. Man kann in keiner Basisklasse Speicher für Attribute von nicht vorhandenen Objekten der Unterklassen freigeben.Dein Code ist von der Idee her auf jeden Fall korrekt. Ein paar Dinge, die mir direkt ins Auge gesprungen sind:
class Kontobasis{ public: Parameterkonstruktor; //Ich gehe davon aus, du weißt wie das geht und hast nur der Einfachheit halber abgekürzt virtual void drucke() = 0; virtual ~Kontobasis //Virtueller Destruktor, notwendig für Vererbung (siehe 8.) private: //protected ist nicht viel besser als public, das wird zu private! string Name; int Bankleitzahl[8]; }; class A : public Kontobasis { // : public Kontobasis für Vererbung benötigt public: Parameterkonstruktor : .... ; //Siehe Kommentar zur Kontobasis Kopierkonstruktor; Zuweisungsoperator; ~Destruktor; void drucke(); protected: private: int* Kontonummer; }; class B : public Kontobasis { //Wieder vergessen public: Parameterkonstruktor : .... ; Kopierkonstruktor; Zuweisungsoperator; ~Destruktor; void drucke(); private: char* Kontonummer; }; class C : public Kontobasis { public: Parameterkonstruktor : .... ; void drucke(); private: char Kontonummer[9]; };
Das sind schonmal die gröbsten Schnitzer.
Auch ist das nur ein ziemlicher Rohentwurf, die Implementierung dürfte dich auch noch einiges an Nerven kosten.Ich hoffe, ich habe nicht allzu viel Stuß palavert (man vergebe mir in anbetracht der späten Stunde) und konnte dir helfen.
MfG Cox.
-
nachrichtentext
-
zu 1.:
Konstruktoren können nicht virtuell sein. Würde auch nicht wirklich Sinn geben, denn wenn du ein Objekt erstellst, was ja den einzigen Aufruf des Konstruktors für ein Objekt darstellt, ist der Typ des zu erstellenden Objekts immer bereits bekannt. Damit wird nie während eines Programms "Fallunterscheidung" zur Laufzeit gemacht werden, und so auch nichts virtuell sein.zu 2.:
Prinzipiell wäre es bestimmt eine schöne Sache, wenn immer die richtigen Zuweisungsoperatoren aufgerufen werden würden. Problematisch wird das nur, weil du, vorausgesetzt du verfügst über einen ordentlichen Satz an Klassen, die alle voneinander abgeleitet wurden (sagen wir mal 5-7), für jede erdenkliche Kombination an Zuweisungen einen eigenen Satz Operatoren schreiben musst.
Sobald nämlich eine zweite Klasse existiert, musst du zwei operator= schreiben.
Einen für operator=(const Basis&) und einen für operator=(const Unterklasse&).
Und das sind zwei unterschiedliche Methoden, die dann nicht mehr einander überschreiben, und so auch nicht richtig aufgerufen werden.
Ist bei meinen kruden Beschreibungen bestimmt ein wenig verwirrend, deshalb empfehle ich als sehr kurze Lektüre:
http://velociraptor.mni.fh-giessen.de/Programmierung/ProgII-htmldir/node9.html#SECTION00093300000000000000zu 3.:
Ja es stimmt. Ich bin gestern wohl irrsinnigerweise von der Definition in der Klassendefinition ausgegangen.
Man kann also abstrakte Funktionen durchaus definieren, doch der Sinn dahinter ist eine andere Sache. Vorausgesetzt, man will diese Funktion auch irgendwann einmal Verwenden, muss man sie eh überschreiben. Denn tut man das nicht, hat man ja wieder eine abstrakte Klasse. Dein Beispiel geht also nicht ganz auf.
Du willst quasi deine Funktion aus einer abgeleiteten Klasse heraus aufrufen. Damit du jedoch überhaupt ein Objekt deiner abgeleiteten Klasse erstellen kannst, musst du sämtliche rein virtuellen Methoden neu definieren, da es sonst, wie gesagt, zu einer abstrakten, nicht instanzierbaren Klasse führt.
Zusammenfassend: Du kannst sie schon definieren. Nur Wozu?Dein nächstes Beispiel allerdings trifft voll und ganz zu. Ich halte es sogar für ausgesprochen gutes Design, das so zu lösen. Obwohl ich an dieser Stelle meine Meinung eher in den Hintergrund rücken möchte. Allzu viel Erfahrung habe ich auch noch nicht
Ich hoffe ich habe jetzt alle Klarheiten beseitigt, ich hau mich jetzt hin.PS: In welchem Zshg. lernst du das Zeug?
-
nachrichtentext