Τελικό τεστ - απαντήσεις

Σχετικά έγγραφα
Κληρονομικότητα. 1 Γενικά. 2 Απλή κληρονομικότητα. 15 Ιανουαρίου 2013

Ερωτήσεις και απαντήσεις στα θέματα του κανονισμού κατάρτισης

Εισαγωγή σε αντικειμενοστραφή concepts. Και λίγη C#

Διαδικαστικός Προγραμματισμός

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

I (JAVA) Ονοματεπώνυμο: Α. Μ.: Δώστε τις απαντήσεις σας ΕΔΩ: Απαντήσεις στις σελίδες των ερωτήσεων ΔΕΝ θα ληφθούν υπ όψην.

I (JAVA) Ονοματεπώνυμο: Α. Μ.: Δώστε τις απαντήσεις σας ΕΔΩ: Απαντήσεις στις σελίδες των ερωτήσεων ΔΕΝ θα ληφθούν υπ όψην.

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

ΥΠΟΛΟΓΙΣΤΕΣ ΙΙ. Τι είναι ; Συναρτήσεις. Παράδειγμα #1. double convert ( double cm ) { double inch;

Κλάσεις και αντικείμενα #include <iostream.h<

Δομημένος Προγραμματισμός

Στη C++ υπάρχουν τρεις τύποι βρόχων: (a) while, (b) do while, και (c) for. Ακολουθεί η σύνταξη για κάθε μια:

Τελεστές ΤΕΛΕΣΤΕΣ. Γεώργιος Παπαϊωάννου ( )

Αντικειμενοστρεφής Προγραμματισμός

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Προγραμματισμός Η/Υ (ΤΛ2007 )

ΣΥΝΑΡΤΗΣΕΙΣ Παραδείγματα χρήσης συναρτήσεων

Προγραμματισμός Υπολογιστών με C++

Υπερφόρτωση τελεστών

Ενδεικτικές λύσεις και στατιστικά

ΥΠΟΛΟΓΙΣΤΕΣ ΙI. Άδειες Χρήσης. Συναρτήσεις I Διδάσκοντες: Αν. Καθ. Δ. Παπαγεωργίου, Αν. Καθ. Ε. Λοιδωρίκης

Εισαγωγή στον Προγραμματισμό με C++

Προγραμματισμός Η/Υ (ΤΛ2007 )

Τι είναι κλάση Κλάση

ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ. Σχηματική παράσταση του προγράμματος. logariasmos

Σύνθεση και Κληρονομικότητα

Δομημένος Προγραμματισμός (ΤΛ1006)

ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 11/3/2008

Pascal. 15 Νοεμβρίου 2011

Ονοματεπώνυμο και ΑΜ: Είχα παραδώσει εργασίες τα εξής ακαδημαϊκά έτη: Διάρκεια: 2,5 ώρες, κλειστά βιβλία και σημειώσεις ΚΑΛΗ ΕΠΙΤΥΧΙΑ!

ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 18/3/2008

3ο σετ σημειώσεων - Πίνακες, συμβολοσειρές, συναρτήσεις

ΠΟΛΥΜΟΡΦΙΣΜΟΣ. 4.1 Κληρονομικότητα και Αρχή της Υποκατάστασης

Διάλεξη 16-17: Πολυμορφισμός (Polymorphism) Διδάσκων: Παναγιώτης Ανδρέου

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Προγραμματισμός Ι (ΗΥ120)

Εισαγωγή στον Προγραμματισμό με C++

Αντικειμενοστραφείς Γλώσσες Προγραμματισμού C++ / ROOT

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πίνακες Κλάσεις και Αντικείμενα

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

7. ΕΙΣΑΓΩΓΗ ΣΤΙΣ ΣΥΝΑΡΤΗΣΕΙΣ

Σύνθεση και Κληρονομικότητα

Τμήμα Πολιτικών Μηχανικών και Μηχανικών Περιβάλλοντος ΠΠΜ 401: Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής, :00-10:00 π.μ.

Προγραμματισμός Ι. Εισαγωγή στην C++ Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Προγραμματισμός Υπολογιστών με C++

Γ7.2 Συμβολοσειρές (Strings) Γ Λυκείου Κατεύθυνσης

Προγραμματισμός H/Y Ενότητα 5: Συναρτήσεις. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

ΤΕΜ-101 Εισαγωγή στους Η/Υ Εξεταστική Ιανουαρίου 2011 Θέματα Β

Αντικειμενοστραφής Προγραμματισμός

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

12. ΑΛΦΑΡΙΘΜΗΤΙΚΑ. υο είδη αλφαριθµητικών Τα αλφαριθµητικά της C πίνακες τύπου char Ta αντικείµενα της κλάσης string

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Constructors

Γραφικά υπολογιστών Εργαστήριο 9 Κλάσεις στην Python. Σκοπός της 9ης άσκησης είναι να μάθουμε αντικειμενοστρεφή προγραμματισμό στην Python.

Aσκήσεις Πράξης 6 - EΠΑΝΑΛΗΠΤΙΚΟ A ΜΕΘΟ ΟΛΟΓΙΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Ι ΕΡΓΑΣΤΗΡΙΟ. 5. Τι τυπώνει το επόµενο πρόγραµµα:

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργώντας δικές μας Κλάσεις και Αντικείμενα

Προγραμματισμός Υπολογιστών με C++ Φύλλο Διαγωνίσματος Ακαδημαϊκό εξάμηνο: Χειμερινό

10 η Διάλεξη C++ - Πίνακες. Δρ. Χρήστος Δρόσος ΑΕΙ ΠΕΙΡΑΙΑ ΤΤ ΤΜΗΜΑ ΑΥΤΟΜΑΤΙΣΜΟΥ

Προγραμματισμός Υπολογιστών με C++

Αντικειμενοστραφείς Γλώσσες Προγραμματισμού C++ / ROOT

ΥΠΟΛΟΓΙΣΤΕΣ ΙI. Άδειες Χρήσης. Συναρτήσεις II Διδάσκοντες: Αν. Καθ. Δ. Παπαγεωργίου, Αν. Καθ. Ε. Λοιδωρίκης

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

ΚΑΛΟΥΠΩΜΑΤΑ & ΜΕΤΑΤΡΟΠΕΣ

Εισαγωγή στον Αντικειμενοστρεφή Προγραμματισμό Διάλεξη #2

Εισαγωγή στον Προγραµµατισµό, Αντώνιος Συµβώνης, ΣΕΜΦΕ, ΕΜΠ,, Slide 6

Προγραμματισμός Η/Υ (ΤΛ2007 )

5ο σετ σημειώσεων - Δείκτες

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 17/1/08

Η γλώσσα προγραμματισμού C

«ΕΙΔΙΚΑ ΘΕΜΑΣΑ ΣΟΝ ΠΡΟΓΡΑΜΜΑΣΙΜΟ ΤΠΟΛΟΓΙΣΩΝ» Κεφάλαιο 4: Αντικειμενοςτρεφήσ Προγραμματιςμόσ

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Constructors, equals, tostring

ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡ/ΣΜΟΣ C++

ΕΡΓΑΣΙΕΣ ΟΝΤΟΚΕΝΤΡΙΚΟΥ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

ΕΡΓΑΣΤΗΡΙΟ 6: Συναρτήσεις και Αναδρομή

Ανάπτυξη και Σχεδίαση Λογισμικού

Προγραμματισμός Υπολογιστών με C++

ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ ΘΕΜΑ: «Σχεδιασμός και ανάπτυξη ιστοσελίδων ηλεκτρονικής εκπαίδευσης (e learning) σε θέματα αντικειμενοστραφή προγραμματισμού.

ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ ΚΑΙ ΠΟΛΥΜΟΡΦΙΣΜΟΣ

Η Γλώσσα Προγραµµατισµού C++ (The C++ Programming Language)

5. ΣΥΝΑΡΤΗΣΕΙΣ. (Πρόχειρο σχέδιο - Μαθήµατος 3) p Συναρτήσεις, που δεν επιστρέφουν κάποια τιµή

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Αναφορές-Παράμετροι

Δομή Προγράμματος C++, Χειρισμός Μεταβλητών και Συναρτήσεις Εισόδου - Εξόδου

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα με πίνακες. Constructors. Υλοποίηση Στοίβας

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργία Κλάσεων και Αντικειμένων

Η γλώσσα προγραμματισμού C

Προγραμματισμός ΙI (Θ)

Εναλλακτικές εντολές για ανάγνωση/εγγραφή

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 6: Φιλικές συναρτήσεις. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

3 Αλληλεπίδραση Αντικειμένων

Ηλεκτρονικοί Υπολογιστές

public void printstatement() { System.out.println("Employee: " + name + " with salary: " + salary);

Η γλώσσα προγραμματισμού C Οι συναρτήσεις στη C (2)

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #2

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Μνήμης Αντικείμενα ως ορίσματα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα ως ορίσματα

Δομημένος Προγραμματισμός

53 Χρόνια ΦΡΟΝΤΙΣΤΗΡΙΑ ΜΕΣΗΣ ΕΚΠΑΙΔΕΥΣΗΣ Σ Α Β Β Α Ϊ Δ Η Μ Α Ν Ω Λ Α Ρ Α Κ Η

Προγραμματισμός Υπολογιστών με C++

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ. Ασκήσεις Επανάληψης

Transcript:

Τελικό τεστ - απαντήσεις Θεωρήστε το παρακάτω πρόγραμμα και απαντήστε στις ερωτήσεις που ακολουθούν. 1 class parent { 2 public: 3 int a; int b; 4 parent(int _a, int _b) {} 5 6 void f1(int x) { cout << " " << endl; } 7 virtual void f2(int x) { cout << " parent::f2" << endl; } 8 }; 9 10 class child : public parent { 11 public: 12 int c; 13 child(int _a, int _b, int _c) : parent(_a, _b) {} 14 15 void f1(int x) { cout << " child:: f1" << endl; } 16 void f2(int x) { cout << " child:: f2(int)" << endl; } 17 void f2(int x, int y) { cout << "child::f2(int, int)" << endl; } 18 void f3(int x) { cout << " child:: f3" << endl; } 19 }; 20 21 void func1( parent p) 22 { p. f1(0); p. f2(0); p. f2(0, 0); p. f3(0); } 23 24 void func2( child c) 25 { c. f1(0); c. f2(0); c. f2(0, 0); c. f3(0); } 26 27 void func3( parent& p) 28 { p. f1(0); p. f2(0); p. f2(0, 0); p. f3(0); } 29 30 int main() 31 { 32 parent p(0, 0); parent p(0, 0, 0); 33 child c(0, 0); child c(0, 0, 0); 34 35 p. f1(0); p. f2(0); p. f2(0, 0); p. f3(0); 36 c. f1(0); c. f2(0); c. f2(0, 0); c. f3(0); 37 38 func1(p); func2(p); func3(p); 39 func1(c); func2(c); func3(c); 40 } 1

Ερώτημα 1: Ποιες από τις κλήσεις των συναρτήσεων func1, func2 και func3 στις γραμμές 22, 25 και 28 επιτρέπονται και ποιες όχι; Σημειώστε Σ δεξία από εκείνες που θεωρείτε ότι επιτρέπονται και Λ στις υπόλοιπες. Η func1 παίρνει μία παράμετρο τύπου parent. Άρα οι κλήσεις που επιτρέπονται στη γραμμή 22 θα είναι εκείνες που επιτρέπονται για ένα αντικείμενο τύπου parent. Για να είναι νόμιμη μία κλήση θα πρέπει αφενός να υπάρχει μέθοδος με αυτό το όνομα και αφετέρου τα πραγματικά και τυπικά ορίσματα να συμφωνούν ως προς το πλήθος και τον τύπο τους. Άρα οι δύο πρώτες κλήσεις p.f1(0) και p.f2(0); επιτρέπονται γιατί η κλάση parent έχει τις μεθόδους f1 και f2 οι οποίες παίρνουν από μία ακέραια παράμετρο η καθεμία. Αντίθετα η κλήση p.f2(0,0); δεν επιτρέπεται γιατί η κλάση parent δε δηλώνει μέθοδο f2(int,int) δηλαδή μέθοδο με όνομα f2 η οποία να παίρνει δύο ορίσματα. Επίσης δεν επιτρέπεται η κλήση p.f3(0); γιατί η κλάση parent δε δηλώνει κάποια μέθοδο με όνομα f3. Τα ίδια ακριβώς ισχύουν και για τις κλήσεις της συνάρτησης func3. Εφόσον περιέχει τις ίδιες κλήσεις και η τυπική της παράμετρος είναι και αυτή τύπου parent δεν θα υπάρχει καμία διαφοροποίηση σε σχέση με την func1. Το γεγονός ότι στην func3 η parent παράμετρος δηλώνεται ως αναφορά δεν έχει καμία επίπτωση σχετικά με το ποιες μέθοδοι μπορούν ή δεν μπορούν να καλούνται. Για τις κλήσεις της func2 με ανάλογο σκεπτικό, εξετάζουμε τη νομιμότητα των κλήσεων ανάλογα με τον τύπο του αντικειμένου για το οποίο καλούνται. Η παράμετρος c της func2 είναι τύπου child. Εφόσον τα αντικείμενα τύπου child έχουν όλα όσα έχουν και τα αντικείμενα τύπου parent και με δεδομένο ότι οι κλήσεις p.f1(0); και p.f2(0); επιτρέπονται στις func1 και func3, τότε θα επιτρέπονται και στη func2. Επίσης επιτρέπεται και η κλήση c.f2(0,0); γιατί στην κλάση child υπάρχει μία μέθοδος f2 με δύο παραμέτρους και η κλήση c.f3(0); γιατί η child δηλώνει και μία μέθοδο f3 με μία ακέραια παράμετρο. Ερώτημα 2: Ποιες από τις εντολές των γραμμών 32-33 και 35-36 επιτρέπονται και ποιες όχι; Σημειώστε τις όπως και στο προηγούμενο. Οι κλήσεις στις γραμμές 32 και 33 είναι δηλώσεις αντικειμένων τύπου parent και child αντίστοιχα. Άρα θα πρέπει να εξετάσουμε για την κάθε περιπτωση αν υπάρχουν constructors με την ίδια υπογραφή, δηλαδή το ίδιο πλήθος παραμέτρων. Η κλάση parent δηλώνει μόνο έναν constructor με δύο ακέραια ορίσματα άρα η δήλωση parent p(0,0); επιτρέπεται ενώ η parent p(0,0,0); όχι. Ανάλογα η κλάση child δηλώνει έναν constructor με τρία ακέραια ορίσματα. Άρα η δήλωση child c(0,0,0); επιτρέπεται ενώ η child c(0,0); όχι. Δε θα πρέπει κάποιος να θεωρήσει ότι το γεγονός ότι η κλάση parent έχει έναν constructor με δύο παραμέτρους συνεπάγεται ότι θα έχει και η child: οι constructors δεν κληρονομούνται. Οι γραμμές 35 και 36 είναι απλές κλήσεις μεθόδων για αντικείμενα τύπου parent και child αντίστοιχα, οπότε ισχύουν όσα ισχύουν και για το ερώτημα 1. Δηλαδή οι δύο πρώτες κλήσεις της γραμμής 35 επιτρέπονται ενώ οι άλλες δύο όχι. Επίσης επιτρέπονται όλες οι κλήσεις της γραμμής 36. Ερώτημα 3: Ποιες από τις κλήσεις των γραμμών 38-39 επιτρέπονται και ποιες όχι; Αιτιολογήστε την απάντησή σας σχετικά με τον τύπο των τυπικών και πραγματικών παραμέτρων. 2

Στις γραμμές 38 και 39 καλούνται οι συναρτήσεις func1, func2 και func3 με παραμέτρους τα αντικείμενα p και c τύπου parent και child αντίστοιχα. Μία κλήση συνάρτησης επιτρέπεται αν το πλήθος και ο τύπος των τυπικών και πραγματικών ορισμάτων συμφωνούν. Άρα οι κλήσεις func1(p); και func3(p); της γραμμής 38 επιτρέπονται γιατί οι συναρτήσεις func1 και func3 δέχονται ένα αντικείμενο τύπου parent ως τυπική παράμετρο και το αντικείμενο p που δίνεται ως πραγματική παράμετρος είναι και αυτό τύπου parent. Αντίστοιχα επιτρέπεται και η κλήση func2(c); της γραμμής 39 όπου δίνεται το αντικείμενο c τύπου child ως πραγματική παράμετρος στη συνάρτηση func2 που έχει τυπική παράμετρο ένα child. Οι κλήσεις func1(c); και func3(c); της γραμμής 39 δίνουν ένα αντικείμενο τύπου child ως παράμετρο σε συναρτήσεις που περιμένουν ένα parent. Δεδομένου όμως ότι η child είναι απόγονος της parent δηλαδή τα αντικείμενα τύπου child είναι αντικείμενα τύπου parent, οι κλήσεις αυτές επιτρέπονται λόγω του μηχανισμού μετατροπής προς τα πάνω (upcasting). Αντίθετα η κλήση func2(p); της γραμμής 38 δεν επιτρέπεται γιατί δίνεται ως πραγματική παράμετρος το p τύπου parent σε μία συνάρτηση που περιμένει μία παράμετρο τύπου child. Αυτό όμως δεν επιτρέπεται γιατί τα αντικείμενα τύπου parent δεν μπορούν να θεωρηθούν ως child. Ερώτημα 4: Αγνοώντας τις κλήσεις της γραμμής 22 που δεν επιτρέπονται, γράψτε τι θα τυπωνόταν στην οθόνη από την κλήση func1(p); της γραμμής 38. Θα τυπωνόταν κάτι διαφορετικό με την κλήση func1(c); της γραμμής 39; Αιτιολογήστε. Αντίστοιχα, γράψτε τι θα τυπωνόταν στην οθόνη από την κλήση func3(p); της γραμμής 38 (αγνοώντας τις κλήσεις της γραμμής 22 που δεν επιτρέπονται. θα τυπωνόταν κάτι διαφορετικό από την κλήση func3(c); της γραμμής 39; Αιτιολογήστε. Η κλήση func1(p); δίνει ένα αντικείμενο τύπου parent ως παράμετρο στη συνάρτηση func1. Όπως αναφέρθηκε και στην απάντηση του ερωτήματος 1, μόνο οι δύο πρώτες από τις τέσσερις κλήσεις της func1 επιτρέπονται, δηλαδή οι p.f1(0); και p.f2(0);. Αυτές καλούν τις μεθόδους f1 και f2 για ένα αντικείμενο τύπου parent. Η κλήση της f1 θα έχει προφανώς ως αποτέλεσμα να κληθεί η μέθοδος f1 της κλάσης parent. Η κλήση της f2 θα έχει ως αποτέλεσμα την κλήση της μεθόδου f2 της κλάσης parent. Το γεγονός ότι η f2 είναι virtual δεν θα έχει καμία επίπτωση αφού το αντικείμενο είναι τύπου parent. Τελικά λοιπόν στην οθόνη θα τυπωθεί το παρακάτω: parent::f2 Η κλήση func1(c); θα τυπώσει στην οθόνη ακριβώς τα ίδια παρόλο που η παράμετρος c είναι τύπου child. Ο λόγος είναι ότι η παράμετρος c τύπου child μπορεί μεν να δοθεί στη συνάρτηση func1 που περιμένει ένα parent μέσω του μηχανισμού upcasting αλλά λόγω του ότι η παράμετρος αυτή δίνεται κατ αξία (by value) και όχι κατ αναφορά (by reference) έχει ως αποτέλεσμα να δημιουργηθεί κατά την εκτέλεση της func1 ένα νέο αντικείμενο p τύπου parent ως αντίγραφο του c και για αυτό το αντίγραφο καλούνται οι μέθοδοι f1 και f2. Το γεγονός ότι το αντικείμενο p φτιάχτηκε ως αντίγραφο του c που ήταν child δεν παίζει κανένα ρόλο. Το νέο αντικείμενο είναι parent και ισχύει για αυτό ότι ισχύει για τα parent. Σημείωστε ότι ο μηχανισμός της πολυμορφικότητας δεν 3

προκαλεί καμία διαφορά όχι γιατί δεν ενεργοποιείται αλλά γιατί το γεγονός ότι δημιουργείται ένα αντίγραφο τύπου parent σημαίνει ότι όταν ενεργοποιηθεί θα αναζητήσει τον πραγματικό τύπο του αντικειμένου για το οποίο καλείται η εικονική μέθοδος f2. Ο πραγματικός τύπος θα είναι ο τύπος του αντιγράφου (parent) και όχι ο τύπος του πρωτότυπου child το οποίο δεν είναι καν ορατό μέσα από την func1. Στην περίπτωση της func3 η διαφορά έγκειται στο γεγονός ότι η παράμετρος p είναι μεν δηλωμένη ως parent αλλά δίνεται κατ αναφορά (by reference) δηλαδή δεν δημιουργείται ένα αντίγραφο της πραγματικής παραμέτρου όταν εκτελείται η func3 αλλά της δίνεται ένας δείκτης προς την πρωτότυπη παράμετρο. Όταν λοιπόν πραγματοποιηθεί η κλήση func3(p); θα δοθεί στη func3 ένας δείκτης σε parent ως παράμετρος. Η κλήση p.f1(); μέσα στη func3 θα έχει ως αποτέλεσμα την κλήση της μεθόδου f1 της κλάσης parent. Η κλήση της μεθόδου f2 θα ενεργοποιήσει το μηχανισμό της πολυμορφικότητας λόγω του ότι η μέθοδος f2 είναι δηλωμένη ως εικονική (virtual) στην κλάση parent. Η C++ θα αναζητήσει τον πραγματικό τύπο της παραμέτρου της και λόγω του ότι της δόθηκε ένας δείκτης προς το πρωτότυπο που είναι πραγματικά τύπου parent, θα καλέσει τη μέθοδο f2 της κλάσης parent. Οπότε στην οθόνη θα τυπωθεί το παρακάτω: parent::f2 Όταν πραγματοποιηθεί η κλήση func3(c) θα δοθεί στη func3 ως παράμετρος ένας δείκτης στο πρωτότυπο child. Όταν η func3 πάει να καλέσει τη μέθοδο f1, θα καλέσει τη μέθοδο f1 του parent. Παρατηρήστε ότι το γεγονός ότι η child κάνει override στη μέθοδο f1 δεν έχει καμία επίπτωση. Η συνάρτηση func3 παίρνει ως παράμετρο ένα δείκτη σε parent οπότε αφού η μέθοδος f1 δεν είναι δηλωμένη ως εικονική, η συνάρτηση func3 καλεί τη μέθοδο f1 του parent παρόλο που η πραγματική της παράμετρος είναι child. Στην περίπτωση της κλήσης της f2 όμως, ενεργοποιείται ο μηχανισμός της πολυμορφικότητας. Η συνάρτηση func3 προσπαθεί να καλέσει τη μέθοδο f2 για την παράμετρο τύπου parent. Επειδή όμως η f2 είναι δηλωμένη ως εικονική, η func3 αναζητά τον πραγματικό τύπο της παραμέτρου της και καλεί την f2 που αντιστοιχεί σε αυτόν. Δεδομένου ότι της δόθηκε δείκτης σε child καλεί τη μέθοδο f2 της κλάσης child. Οπότε στην οθόνη θα τυπωθεί το εξής: child::f2 Ερώτημα 5: Δηλώστε μία κλάση scanner με μία μέθοδο fax και μία μέθοδο status. Δηλώστε επίσης μία κλάση fax με τις μεθόδους send, receive και status. Δηλώστε μία κλάση multi που κληρονομεί και από τις δύο και δώστε ένα παράδειγμα χρήσης της στο οποίο να φαίνεται ότι για αντικείμενα της νέας κλάσης μπορούν να κληθούν όλες οι παραπάνω μέθοδοι. Αναλύστε τον λόγο για τον οποίο δεν μπορούμε να καλέσουμε τη μέθοδο status για αντικείμενα της νέας κλάσης. Δώστε λύση στο πρόβλημα ώστε να μπορούμε να καλέσουμε μία μέθοδο status για τη νέα κλάση η οποία να καλεί τις αντίστοιχες μεθόδους των βασικών κλάσεων. Οι δηλώσεις των κλάσεων scanner και fax θα μπορούσαν να είναι 1 class scanner { 4

2 public: 3 void scan() {... } 4 void status() {... } 5 }; 6 7 class fax { 8 public: 9 void send() {... } 10 void receive() {... } 11 void status() {... } 12 }; Η κλάση multi μπορεί να δηλωθεί απλά ως απόγονος των scanner και fax οπότε αυτόματα κληρονομεί όλες τις μεθόδους τους: 1 class multi : public scanner, public fax { 2 3 }; Έτσι θα μπορούσαμε να δηλώσουμε ένα αντικείμενο τύπου multi και για αυτό να καλέσουμε οποιαδήποτε από τις μεθόδους των βασικών του κλάσεων: 1 int main() 2 { 3 multi a; 4 a.send(); // Kalei thn send toy fax 5 a.scan(); // Kalei thn scan toy scanner 6 a. receive(); // Kalei thn receive toy fax 7 } Ο λόγος για τον οποίο δεν μπορούμε να πραγματοποιήσουμε μία κλήση σαν την a.status(); είναι ότι αυτή είναι αμφίσημη. Δεδομένου ότι η κλάση multi κληρονομεί τόσο την status από την scanner όσο και την status από την fax σημαίνει ότι η C++ δεν μπορεί να διαχωρίσει ποιαν από τις δύο θέλουμε να καλέσουμε όταν καλούμε την status για ένα αντικείμενο multi. Μπορούμε να λύσουμε το πρόβλημα δηλώνοντας μία μέθοδο status στην κλάση multi. Αυτή κάνει override και στις δύο status των scanner και fax οπότε η κλήση a.status(); δεν είναι πια αμφίσημη, δεδομένου ότι θα καλέσει τη status του multi αφού αυτή υπάρχει. Μπορούμε να γράψουμε ό,τι κώδικα θέλουμε στη νέα status. Θα μπορούσαμε απλώς να καλέσουμε μέσα από αυτήν τις status των βασικών της κλάσεων χρησιμοποιώντας τον τελεστή ::. Οπότε η δήλωση της multi θα μπροούσε να είναι αυτή: 1 class multi : public scanner, public fax { 2 public: 3 void status() { 4 scanner::status(); 5 fax::status(); 6 } 7 }; 5