Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

early binding (frühe Bindung) late binding (späte Bindung)

Ähnliche Präsentationen


Präsentation zum Thema: "early binding (frühe Bindung) late binding (späte Bindung)"—  Präsentation transkript:

1 early binding (frühe Bindung) late binding (späte Bindung)

2 Ausgangspunkt sind wieder die Klassen der letzten Präsentation:

3 #include "stdafx.h" #include <iostream> #include <time.h> using namespace std; class A{ public: A(int i); void hallo(); int x; }; class B: public A{ B(int i); int y;

4 A::A(int i){ x = i; }; void A::hallo(){ cout << "Ich bin A" << "x=" << x << endl; B::B(int i):A(i-2){ x = i-1; y = i; void B::hallo(){ cout << "Ich bin B" << "x=" << x << "y=" << y << endl;

5 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 ? A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 ? Welcher Wert welcher Speicherzelle wird durch die gleich folgenden Anweisungen links verändert ? Auf welches Objekt (a oder b) zeigt ap ? Vom Zufall abhängig, zeigt ap entweder auf das Objekt a oder auf das Objekt b.

6 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 ? A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 ? Angenommen, ap zeigt auf b. Welchen Wert hat dann ap ?

7 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 Angenommen, ap zeigt auf b. Welchen Wert hat dann ap ?

8 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200

9 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200 Auf welches x würde dann die Anweisung ap->x = 13 zugreifen ? Es gibt 2 Möglichkeiten: b.A::x oder b.B::x Da sich der Compiler schon beim Compilieren (und nicht erst während der Laufzeit) entscheiden muss, kann es nicht ...

10 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200 dieses x existiert in a und b .... B::x sein, da diese Komponente (falls ap auf a zeigt) nicht existiert. Dagegen existiert (egal ob ap auf a oder b zeigt) immer die Komponente A::x. Diesen Vorgang des Compilers nennt man early binding (frühe Bindung).

11 a b ap Adr 0100 x 10 Adr 0200 A::x 18 x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 18 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200 Also wird der Wert von x im Objekt b verändert auf:

12 a b ap Adr 0100 x 10 Adr 0200 A::x x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200

13 a b ap Adr 0100 x 10 Adr 0200 A::x 13 x 19 y 20 Adr 0300 0200 A a(10);
B b(20); A *ap; Adr a 0100 x 10 Adr b 0200 A::x 13 x 19 y 20 if(rand()%2)==1) ap = &a; else ap = &b; ap->x=13; Adr ap 0300 0200 Also: Der Typ der Zeigervariablen, hier also A, und nicht der Typ des Objekts auf den ap während der Laufzeit zeigt, hier also B, bestimmt welches Mitglied (Member) von *ap angesprochen wird.

14 Neue Frage

15 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 ? Welcher Wert welcher Speicherzelle wird durch die folgenden Anweisungen links verändert ? Auf welches Objekt (a oder b) zeigt ap ? aus Platzgründen: hier steht wie vorher: rand()%2 = =1 Vom Zufall abhängig, zeigt ap entweder auf das Objekt a oder auf das Objekt b.

16 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 ? Angenommen, ap zeigt auf b. Welchen Wert hat dann ap ?

17 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300

18 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0200

19 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0200 Auf welches hallo() würde dann die Anweisung ap->hallo() zugreifen ? Es gibt 2 Möglichkeiten: b.A::hallo() oder b.B::hallo() Da sich der Compiler schon beim Compilieren (und nicht erst während der Laufzeit) entscheiden muss, kann es nicht ...

20 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0200 dieses hallo() existiert in a und b .... B::hallo() sein, da diese Methode (falls ap auf a zeigt) nicht zu A gehört. Dagegen existiert (egal ob ap auf a oder b zeigt) immer die Methode A::hallo(). Diesen Vorgang des Compilers nennt man early binding (frühe Bindung).

21 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0200 Also: Der Typ der Zeigervariablen, hier also A, und nicht der Typ des Objekts auf den ap während der Laufzeit zeigt, hier also b, bestimmt welches Mitglied (Member) von *ap angesprochen wird.

22 Mögliche Speicherbelegung beim obigen Programm (hier nochmals das Programm)

23 int main(){ A a(10); B b(20); A
int main(){ A a(10); B b(20); A *ap; srand((unsigned)time(NULL)); if(rand()%2==1){ ap = &a; } else{ ap = &b; } ap->x = 13; ap->hallo(); return(0); }

24 Annahme: 1) Die Adressen wurden willkürlich gewählt. In der 4
Annahme: 1) Die Adressen wurden willkürlich gewählt. In der 4. Spalte stehen die Werte also die Inhalte der Adressen nachdem die letzte Anweisung des Programms abgearbeitet wurde. 2) Zufallsbedingt soll der Körper des else Teils der if-Verzweigung (also ap = &b) ausgeführt werden.

25 Adresse Symbol besteht Inhalt 0100 a x 10 ... 0200 b A::x 13 B::x 19 y
0300 ap 0500 A::hallo() Anweisungen 0600 B::hallo()

26 Neue Frage

27 Wie kann man erreichen, dass bei einem Verweis auf ein Objekt die Methode der Klasse dieses Objektes zur Laufzeit aufgerufen wird und nicht die gleichnamige Methode der Klasse des Typs des Verweises beim Compilieren ? Kurz: Wie kann man early binding umgehen ? Wie wird dies programmtechnisch realisiert ?

28 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0100 Angenommen, ap zeigt zufallsbedingt auf a. Dann soll die Anweisung ap->hallo() auf die folgende Methode zugreifen: Die Methode hallo(), der Klasse des Objekts, auf das ap während der Laufzeit zeigt, also A::hallo().

29 a b ap Adr 0100 x 10 hallo() Adr 0200 A::x 18 x 19 y 20 A::hallo()
A a(10); B b(20); A *ap; Adr a 0100 x 10 hallo() Adr b 0200 A::x 18 x 19 y 20 A::hallo() B::hallo() if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 0200 Angenommen, ap zeigt zufallsbedingt auf b. Dann soll die Anweisung ap->hallo() auf die folgende Methode zugreifen: Die Methode hallo(), der Klasse des Objekts, auf das ap während der Laufzeit zeigt, also B::hallo().

30 Das dazugehörige Programm ist das Gleiche wie oben, nur dass die Methode hallo() bei der Deklaration den Bezeichner virtual bekommt.

31 Das Programm

32 #include "stdafx. h" #include <iostream> #include <time
#include "stdafx.h" #include <iostream> #include <time.h> using namespace std;

33 class A{ public: A(int i); virtual void hallo(); int x; }; class B: public A{ public: B(int i); virtual void hallo(); int x; int y; }; Der Bezeichner virtual vererbt sich und muß daher nicht mehr (kann aber) in den Subklassen wiederholt werden. Durch den Bezeichner virtual wird hallo() eine virtuelle Funktion. Die Verwendung von virtual ist nur innerhalb einer Klassendeklaration zulässig.

34 A::A(int i){ x = i; }; void A::hallo(){ cout <<"Ich bin A und " << "x= " << x << endl; }; B::B(int i):A(i-2){ x = i-1; y = i; }; void B::hallo(){ cout << "Ich bin B" << "x=" << x << "y=" << y << endl; };

35 int main(){ A a(10); B b(20); A
int main(){ A a(10); B b(20); A *ap; srand((unsigned)time(NULL)); if(rand()%2==1){ ap = &a; } else{ ap = &b; } ap->x = 13; ap->hallo(); return(0); }

36 Neue Frage

37 Wie wird dies technisch im Speicher realsiert ?

38 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 ? Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() vt_A ist ein Verweis (Adresse) auf eine Tabelle (virtual function pointer table), in der wiederum die Adressen der virtuellen Methoden der Klasse A stehen, hier also die Adresse der Methode A::hallo() vt_B ist ein Verweis (Adresse) auf eineTabelle (virtual function pointer table), in der wiederum die Adressen der virtuellen Methoden der Klasse B stehen, hier also die Adresse der Methode B::hallo()

39 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 ? Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() Angenommen, ap zeigt zufallsbedingt auf a. Welchen Wert hat dann ap ?

40 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo()

41 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 100 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() Welche Adresse wird dann beim Aufruf von hallo() in der folgenden Anweisung angesprochen ? ap->hallo() ein ?

42 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 100 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() 0500 Welche Methode wird also aufgerufen ? 096 A::hallo() 0100 *(ap-4)

43 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 ? Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() Angenommen, ap zeigt zufallsbedingt auf b. Welchen Wert hat dann ap ?

44 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo()

45 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 200 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() Welche Adresse wird dann beim Aufruf von hallo() in der folgenden Anweisung angesprochen ? ap->hallo() ein ?

46 a b ap Adr 096 &vt_A 0100 x 10 Adr 0196 &vt_B 0200 A::x 18 x 19 y 20
A a(10); B b(20); A *ap; Adr a 096 &vt_A 0100 x 10 Adr b 0196 &vt_B 0200 A::x 18 x 19 y 20 if(...) ap = &a; else ap = &b; ap->hallo(); Adr ap 0300 200 Adr vt_B 0600 B::hallo() Adr vt_A 0500 A::hallo() 0600 Welche Methode wird also aufgerufen ? 0196 B::hallo() 0200 *(ap-4)

47 Mögliche Speicherbelegung beim obigen Programm (hier nochmals das Programm)

48 Annahme: 1) Die Adressen wurden willkürlich gewählt. In der 4
Annahme: 1) Die Adressen wurden willkürlich gewählt. In der 4. Spalte stehen die Werte, also die Inhalte der Adressen nachdem die letzte Anweisung des Programms abgearbeitet wurde. 2) Zufallsbedingt soll der Körper der if-Verzweigung (also ap = bp) ausgeführt werden. 3) Zwischen den Zeilen stehen platzbedingt keine (durch ... getrennten) weiteren Adressen.

49 Adresse Symbol besteht Inhalt 096 a &vt_A 0500 0100 x 10 0196 b &vt_B
0600 0200 A::x 13 B::x 19 y 20 0300 ap vt_A &A::hallo() 0700 vt_B &B::hallo() 0800 A::hallo() Anweisungen B::hallo()

50 Ist early binding (frühe Bindung) auch einfacher möglich
Ist early binding (frühe Bindung) auch einfacher möglich ? (ohne Pointer)

51 Das (einfachere) Programm ist das Gleiche wie oben, nur dass statt dem Pointer *ap ein Objekt der Klasse A verwendet wird.

52 #include "stdafx. h" #include <iostream> #include <time
#include "stdafx.h" #include <iostream> #include <time.h> using namespace std;

53 class A{ public: A(int i); virtual void hallo(); int x; }; class B: public A{ public: B(int i); virtual void hallo(); int x; int y; }; virtual virtual

54 A::A(int i){ x = i; }; void A::hallo(){ cout <<"Ich bin A und " << "x= " << x << endl; }; B::B(int i):A(i-2){ x = i-1; y = i; }; void B::hallo(){ cout << "Ich bin B" << "x=" << x << "y=" << y << endl; };

55 int main(){ A a(10); B b(20); A z(123); srand((unsigned)time(NULL)); if(rand()%2==1){ z = a; } else{ z = b; } z.x = 13; z.hallo(); return(0); }

56 Warum wird hier kein late Binding gemacht ?

57 Warum wird hier kein late Binding gemacht ?

58 int main(){ A a(10); B b(20); A z(123); srand((unsigned)time(NULL)); if(rand()%2==1){ z = a; } else{ z = b; } z.x = 13; z.hallo(); return(0); } Durch diese Deklaration ist das Objekt z immer vom Klassentyp A. Deshalb wird hier immer early binding gemacht, ganz egal, ob man der Methode hallo den Bezeichner virtual gegeben hat.


Herunterladen ppt "early binding (frühe Bindung) late binding (späte Bindung)"

Ähnliche Präsentationen


Google-Anzeigen