Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

08.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.

Ähnliche Präsentationen


Präsentation zum Thema: "08.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure."—  Präsentation transkript:

1 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure II Prof. Dr. Gisbert Dittrich

2 16-2 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Gliederung: Virtuelle Methoden Bindung von Objekten (möglich): – Unterklasseobjekt an Oberklasseobjekt zu binden Bindung von Methoden: – statisch (zur Übersetzung) – dynamisch (zur Laufzeit) --> virtuelle Methoden Beispiel : Früchte: - konventionell - mit virtuellen Methoden Phänomene bei der Verwendung virtueller Methoden – virtuell wirkt nur bei Einsatz von Zeigern – virtuelle Methode muß nicht notwendig neu definiert werden – rein virtuelle Methoden: Syntax. "= 0" müssen später (re)definiert werden Objekte nur zu Klassen instanziierbar, für die Methoden definiert sind.

3 16-3 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Beispiel: Früchte Zu berücksichtigende Klassifikation: Hülsenfrüchte: Erbsen, Bohnen Obst: Äpfel, Birnen – Südfrüchte: Apfelsinen, Bananen Attribut(e): die Frucht Methoden Konstruktoren Druck – druckt den Namen der Frucht und die Zugehörigkeit zur Klasse

4 16-4 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Klassifikationshierarchie

5 16-5 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Gemeinsam char * dieFrucht. Für alle Objekte der Klassenhierarchie zugreifbar. --> protected Druck sollte (letztendlich) für jedes Objekt angeben, aus welcher Klasse es stammt.

6 16-6 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Deklaration der Klasse Frucht class Frucht { protected: char * dieFrucht; public: Frucht(char *); void Druck(); }; Konstruktor Name der konkreten Frucht

7 16-7 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Sieht nach, wie lang die Zeichenkette sein muß, allokiert entsprechend Kopiert das Argument in die neue Zeichenkette Deklaration der Methoden // int strlen(char *); // void strcpy(char *, char *); Frucht::Frucht(char * s) { dieFrucht = new char[strlen(s)]; strcpy(dieFrucht, s); }

8 16-8 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Deklaration der Methoden void Frucht::Druck() { cout << "(Frucht) " << dieFrucht << endl; }

9 16-9 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Deklaration der Klasse Hfrucht class Hfrucht: public Frucht { public: Hfrucht(char *); void Druck(); }; Hfrucht::Hfrucht(char * s) : Frucht(s) {} void Hfrucht::Druck() { cout << "(Hfrucht) " << dieFrucht << endl; } Oberklasse ist Frucht, erben ist public Konstruktor für Hfrucht nur Aufruf des Konstruktors der Oberklasse Neudefinition der Methode Druck

10 16-10 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Weitere Deklarationen Klasse Obst als Unterklasse von Frucht : völlig analog zum Vorgehen bei Frucht Klasse Suedfruechte als Unterklasse von Obst: Vorgehen ebenfalls völlig analog.

11 16-11 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Hauptprogramm Frucht * ruebe = new Frucht("Rübe"); ruebe->Druck(); Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane"); banane->Druck(); Ausgabe: (Frucht) Rübe (Hfrucht) Erbse (Obst) Apfel (Südfrucht) Banane

12 16-12 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden (jeder Apfel ist Frucht etc.) Hauptprogramm (Forts.) Ausgabe: (Frucht) Frucht (Frucht) Apfel (Frucht) Erbse (Obst) Obst (Obst) Banane Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); Obst * g = new Obst("Obst"); g->Druck(); g = banane; g->Druck();

13 16-13 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Vorlage EED EINI II, SS 99; // überarbeitet: GD // demonstriert Vererbung: // noch ohne virtuelle Methoden #include void strcpy(char * nach, char * von); int strlen(char * r); class Frucht { protected: char * dieFrucht; public: Frucht(char *); void Druck(); }; Frucht::Frucht(char * s) { dieFrucht = new char[strlen(s)]; strcpy(dieFrucht, s); } void Frucht::Druck() { cout << "(Frucht) " << dieFrucht << endl; } // class Hfrucht: public Frucht { public: Hfrucht(char *); void Druck(); }; Hfrucht::Hfrucht(char * s) : Frucht(s) {} void Hfrucht::Druck() { cout << "(Hfrucht) " << dieFrucht << endl; } // class Obst: public Frucht { public: Obst(char *); void Druck(); }; Obst::Obst(char * s) : Frucht(s) {} void Obst::Druck() { cout << "(Obst) " << dieFrucht << endl; } // class SuedFrucht: public Obst { public: SuedFrucht(char *); void Druck(); }; SuedFrucht::SuedFrucht(char * s) : Obst(s) {} void SuedFrucht::Druck() { cout << "(Suedfrucht) " << dieFrucht << endl; } // int main() { cout << "\nZuweisungen: \n"; Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane"); banane->Druck(); cout << "\nhier: "; cout << "\nZuweisung an Zeiger auf Frucht: \n"; Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); cout << "\nda: "; cout << "\nZuweisung an Zeiger auf Obst: \n"; Obst * g = new Obst("Obst"); g- >Druck(); g = banane; g->Druck(); cout << "fertig"; } // void strcpy(char * nach, char * von) { while (*nach++ = *von++); } int strlen(char * r) { int f = 0; while (r[f++]); return f; }

14 16-14 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 1 class Frucht { protected: char * dieFrucht; public: Frucht(char *); void Druck(); }; Frucht::Frucht(char * s) { dieFrucht = new char[strlen(s)]; strcpy(dieFrucht, s); }

15 16-15 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 2 void Frucht::Druck() { cout << "(Frucht) " << dieFrucht << endl;} class Hfrucht: public Frucht { public: Hfrucht(char *); void Druck();}; Hfrucht::Hfrucht(char * s): Frucht(s) {} void Hfrucht::Druck() { cout << "(Hfrucht) " << dieFrucht << endl;}

16 16-16 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 3 class Obst: public Frucht { public: Obst(char *); void Druck();}; Obst::Obst(char * s) : Frucht(s) {} void Obst::Druck() { cout << "(Obst) " << dieFrucht << endl;}

17 16-17 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 4 class SuedFrucht: public Obst { public: SuedFrucht(char *); void Druck();}; SuedFrucht::SuedFrucht(char * s) : Obst(s) {} void SuedFrucht::Druck() { cout << "(Suedfrucht) " << dieFrucht << endl;} // int main() { cout << "\nZuweisungen: \n"; Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane"); banane->Druck(); cout << "\nhier: "; cout << "\nZuweisung an Zeiger auf Frucht: \n"; Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); cout << "\nda: "; cout << "\nZuweisung an Zeiger auf Obst: \n"; Obst * g = new Obst("Obst"); g- >Druck(); g = banane; g->Druck(); cout << "fertig"; } // void strcpy(char * nach, char * von) { while (*nach++ = *von++); } int strlen(char * r) { int f = 0; while (r[f++]); return f; }

18 16-18 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 5 int main() { cout << "\nZuweisungen: \n"; Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane"); banane->Druck(); cout << "\nhier: ";

19 16-19 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 6; main-Fortsetzung cout << "\nZuweisung an Zeiger auf Frucht: \n"; Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); cout << "\nda: "; cout << "\nZuweisung an Zeiger auf Obst: \n"; Obst * g = new Obst("Obst"); g->Druck(); g = banane; g->Druck(); cout << "fertig";} Fruechte_nicht_ virtuell

20 16-20 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte, ohne virtuelle Methoden // Fortsetzung 7 void strcpy(char * nach, char * von) { while (*nach++ = *von++); } int strlen(char * r) { int f = 0; while (r[f++]); return f; }

21 16-21 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Was lernen wir daraus? Zuweisungen sind entlang der Vererbungs- hierarchie möglich: Ein Objekt einer Klasse kann einem Objekt einer Oberklasse zugewiesen werden. Bei der Ausführung von Methoden wird statisch vorgegangen: Die Methode des Objekts wird ausgeführt, die schon zur Übersetzung zu erkennen war.

22 16-22 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Statische Methodenausführung Frucht * f Frucht - Druck für f Zuweisung von apfel ( Obst ) an f Hier also Auswahl der Methode zur Definitions- zeit.

23 16-23 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Bindungen statisch: Die Methode, die zur Zeit der Klassendefinition für das Objekt definiert wurde, wird verwendet. dynamisch: Die Methode, die zur Zeit der Benutzung für das Objekt verfügbar ist, wird verwendet. (Gelegentlich/eigentlich erwünscht.)

24 16-24 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Dynamische Methodenausführung Frucht * f Obst - Druck für f Zuweisung von apfel ( Obst ) an f Hier also Auswahl der Methode zur Lauf Lauf- zeit.

25 16-25 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Virtuelle Methoden Dynamische Methoden, (also Methoden, die zur Laufzeit gebunden werden sollen,) werden in der Oberklasse durch virtual gekennzeichnet. Wenn diese Methoden beim Vererben redefiniert werden, so wird beim Aufruf für ein Objekt einer Unterklasse diejenige Methode ausgeführt, die sich aus dem Laufzeit-Typ des Objekts ergibt.

26 16-26 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Beispiel class Frucht { protected: char * dieFrucht; public: Frucht(char *); virtual void Druck(); }; Kennzeichnung der Methode als virtual hat den Effekt, daß Aufrufe für Instanzen von Unterklassen dynamisch die entsprechende Methode suchen.

27 16-27 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Konsequenz Ausgabe: (Frucht) Frucht (Obst) Apfel (Hfrucht) Erbse (Obst) Obst (Südfrucht) Banane Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); Obst * g = new Obst("Obst"); g->Druck(); g = banane; g->Druck();

28 16-28 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Vorgabe EED EINI II, SS 99 // überarbeitet: GD // demonstriert Vererbung: // jetzt mit virtuellen Methoden // #include class Frucht { protected: char * dieFrucht; public: Frucht(char *); virtual void Druck ();}//virtual! Frucht::Frucht(char * s) { dieFrucht = new char[strlen(s)]; strcpy(dieFrucht, s); } void Frucht::Druck() { cout << "(Frucht) " << dieFrucht << endl; } // class Hfrucht: public Frucht { public: Hfrucht(char *); void Druck(); }; Hfrucht::Hfrucht(char * s) : Frucht(s) {} void Hfrucht::Druck() { cout << "(Hfrucht) " << dieFrucht << endl; } // class Obst: public Frucht { public: Obst(char *); void Druck(); }; Obst::Obst(char * s) : Frucht(s) {} void Obst::Druck() { cout << "(Obst) " << dieFrucht << endl; } // class SuedFrucht: public Obst { public: SuedFrucht(char *); void Druck(); }; SuedFrucht::SuedFrucht(char * s) : Obst(s) {} void SuedFrucht::Druck() { cout << "(Suedfrucht) " << dieFrucht << endl; } // int main() { cout << "Zuweisungen: \n"; Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane"); banane->Druck(); cout << "\nhier: "; cout << "\nZuweisung an Zeiger auf Frucht: \n"; Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); cout << "\nda: "; cout << "\nZuweisung an Zeiger auf Obst: \n"; Obst * g = new Obst("Obst"); g- >Druck(); g = banane; g->Druck(); cout << "fertig"; }

29 16-29 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 1 //Vererbung: jetzt mit virtuellen Methoden Frucht::Frucht(char * s) { dieFrucht = new char[strlen(s)]; strcpy(dieFrucht, s); } void Frucht::Druck() { cout << "(Frucht) " << dieFrucht << endl; }

30 16-30 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 2 //Vererbung: jetzt mit virtuellen Methoden class Hfrucht: public Frucht { public: Hfrucht(char *); void Druck();}; Hfrucht::Hfrucht(char * s) : Frucht(s) {} void Hfrucht::Druck() { cout << "(Hfrucht) " << dieFrucht << endl;}

31 16-31 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 3 //Vererbung: jetzt mit virtuellen Methoden class Obst: public Frucht { public: Obst(char *); void Druck();}; Obst::Obst(char * s) : Frucht(s) {} void Obst::Druck() { cout << "(Obst) " << dieFrucht << endl; }

32 16-32 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 4 //Vererbung: jetzt mit virtuellen Methoden class SuedFrucht: public Obst { public: SuedFrucht(char *); void Druck();}; SuedFrucht::SuedFrucht(char * s) : Obst(s) {} void SuedFrucht::Druck() { cout << "(Suedfrucht) " << dieFrucht << endl; }

33 16-33 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 5 //Vererbung: jetzt mit virtuellen Methoden int main() { cout << "Zuweisungen: \n"; Hfrucht * erbse = new Hfrucht("Erbse"); erbse->Druck(); Obst * apfel = new Obst("Apfel"); apfel->Druck(); SuedFrucht * banane = new SuedFrucht("Banane");banane->Druck(); cout << "\nhier: "; cout << "\nZuweisung an Zeiger auf Frucht: \n";

34 16-34 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // Fruechte; Fortsetzung 6 //Vererbung: jetzt mit virtuellen Methoden // Fortsetzung: main Frucht * f = new Frucht("Frucht"); f->Druck(); f = apfel; f->Druck(); f = erbse; f->Druck(); cout << "\nda: "; cout << "\nZuweisung an Zeiger auf Obst: \n"; Obst * g = new Obst("Obst"); g->Druck(); g = banane; g->Druck(); cout << "fertig"; } Fruechte_virtuell

35 16-35 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Ausgabe Zuweisungen: (Umbruch geändert G.D.) (Hfrucht) Erbse (Obst) Apfel (Suedfrucht) Banane hier: Zuweisung an Zeiger auf Frucht: (Frucht) Frucht (Obst) Apfel (Hfrucht) Erbse da: Zuweisung an Zeiger auf Obst: (Obst) Obst (Suedfrucht) Bananefertig

36 16-36 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Achtung: Zeiger notwendig! Ausgabe (Obst) Obst statisch (Obst) Banane Obst p = Obst("Obst statisch"); p.Druck(); p = *banane; p.Druck(); Hier wird trotz der virtual - Vereinbarung statisch gebunden (es wird kein Zeiger verwendet)

37 16-37 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Anmerkung Eine als virtuell definierte Methode muß nicht in jeder abgeleiteten Klasse redefiniert werden. Bei der Bestimmung der konkret zu verwendenden Methode wird der Vererbungsbaum von der entsprechenden Klasse aus nach oben durch- wandert, bis eine Methode des gesuchten Namens gefunden ist.

38 16-38 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Beispiel class X { public: virtual void zeige();}; class Y: public X { public: void zeige();}; class Z : public Y {}; void X::zeige() { cout << "X"; } void Y::zeige() { cout << "Y"; } int main() { X* zz[4] = {new X, new Z, new X, new Y}; for (int i = 0; i < 4; i++) zz[i]->zeige(); return 0; } Ausgabe: XYXY

39 16-39 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Rein virtuelle Methoden Es kann sinnvoll sein, die Definition einer Methode zu verzögern, so daß sie erst bei der Definition der Erben definiert wird. Diese Methoden heißen rein virtuell.

40 16-40 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Beispiel class X { public: virtual void deute() = 0; void zeige(); }; void X::zeige() { cout << "Aufruf von deute aus: "; deute(); } Das ist neu

41 16-41 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Anmerkungen Die Methode deute wird als virtuell deklariert. Sie bleibt undefiniert (hat also keinen Block als Definition); das wird festgelegt durch =0 nach der Angabe der Signatur. Erben der Klasse müssen die Definition der Methode also nachholen.

42 16-42 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Anmerkungen (Forts.) Klassen, die rein virtuelle Methoden enthalten, können nicht instanziiert werden. – Die Objekte könnten ja die entsprechende Methode mangels Programmtextes nicht ausführen. Solche Klassen heißen abstrakt. Beachte: Rein virtuelle Methoden können bei der Definition anderer Methoden der Klasse verwendet werden.

43 16-43 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Hier wird die Definition der Methode deute nachgeholt Fortsetzung des Beispiels (1) class Y: public X { public: void deute(); }; void Y::deute() { cout << "Y" << endl;} Analog: class Z

44 16-44 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden Fortsetzung des Beispiels (2) int main() { X* zz[2] = {new Y, new Z}; for (int i = 0; i < 2; i++) zz[i]->zeige(); return 0; } Ausgabe Aufruf von deute aus: Y Aufruf von deute aus: Z

45 16-45 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // AbstraktXYZ.cpp // Vorlage EED EINI II, SS 99; // überarbeitet GD // Vererbung: virtuelle Methoden #include class X { public: virtual void deute() = 0; void zeige();}; void X::zeige() { cout << "Aufruf von deute aus: "; deute();} class Y: public X { public: void deute(); }; void Y::deute() { cout << "Y" << endl; } class Z : public X { public: void deute(); }; void Z::deute() { cout << "Z" << endl; } int main() { X* zz[2] = {new Y, new Z}; for (int i = 0; i < 2; i++) zz[i]->zeige(); }

46 16-46 Prof. Dr. G. Dittrich EINI II Kap. 16: Virtuelle Methoden // AbstraktXYZ.cpp; Fortsetzung class Y: public X { public: void deute();}; void Y::deute() { cout << "Y" << endl; } class Z : public X { public: void deute();}; void Z::deute() { cout << "Z" << endl; } int main() { X* zz[2] = {new Y, new Z}; for (int i = 0; i < 2; i++) zz[i]->zeige(); return 0;} AbstraktXYZ


Herunterladen ppt "08.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure."

Ähnliche Präsentationen


Google-Anzeigen