Είσοδος & Έξοδος στη C++ Ι

Slides:



Advertisements
Παρόμοιες παρουσιάσεις
Το αλφαριθμητικό (string)
Advertisements

Προγραμματισμός Ι (αποφύγετέ τον!) 3) Διακοπτόμενος βρόχος: (αποφύγετέ τον!) float energy;......while(TRUE){drink_water(); if(energy
Βασικές Αρχές Ψηφιακής Τεχνολογίας
Στατική Συμβολική Παραγώγιση Λάμδα Εκφράσεων στην C++
Ένα απλό πρόγραμμα σε C /* ********************************************* * This program prints out the sentence “This is a test.” * *********************************************
POINTERS, AGGREGATION, COMPOSITION. POINTERS TO OBJECTS.
ΜΑΘΗΜΑ: ΓΛΩΣΣΑ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ C++ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Δευτέρα, 30 Ιουνίου 2014Δευτέρα, 30 Ιουνίου 2014Δευτέρα, 30 Ιουνίου 2014Δευτέρα, 30 Ιουνίου 2014Τμ.
DATA MINING LECTURE 6 Mixture of Gaussians and the EM algorithm
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
Αναδρομη και static Γραψετε την συναρτηση sequence_size που διαβαζει μια απροσδιοριστου μεγεθους σειρας και υπολογιζει και τυπωνει το μεγεθος της. int.
Γλώσσα Προγραμματισμού
Προγραμματισμός Ι Παράδειγμα: Παράδειγμα: Να γραφεί πρόγραμμα που επιλύει δευτεροβάθμιες εξισώσεις. Να δέχεται ως είσοδο τους συντελεστές της εξίσωσης.
Τύποι πραγματικών αριθμών
ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Πίνακες Κλάσεις και Αντικείμενα.
ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ Φροντιστήρια Εισηγητής: Σπύρος Αργυρόπουλος Μέλος ΕΤΕΠ Εργαστήριο Προγραμματισμού & Τεχνολογίας Ευφυών Συστημάτων.
Μήτρες (templates)  Μία μήτρα είναι ένα κομμάτι κώδικα που περιέχει παραμέτρους οι οποίες δέχονται ως τιμές τύπους δεδομένων.  Είναι ένας μηχανισμός.
1 Τμήμα Μηχανικών Ηλεκτρονικών Υπολογιστών και Πληροφορικής Πανεπιστήμιο Πατρών ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΙΙ (C++) Δομημένος Προγραμματισμός και Δομές.
ΗΥ150 – Προγραμματισμός Ξενοφών Ζαμπούλης ΗΥ-150 Προγραμματισμός Ταξινόμηση και Αναζήτηση.
Προγραμματισμός Ι Προτάσεις επανάληψης - γενικά επαναλαμβάνουν ένα μπλοκ προτάσεωνΟι προτάσεις επανάληψης επαναλαμβάνουν ένα μπλοκ προτάσεων είτε για όσες.
ΛΟΓ201: Τεχνολογία Λογισμικού ΙΙ Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ201:
1 Ολυμπιάδα Πληροφορικής Μάθημα 3. 2 Στόχοι μαθήματος Δομή Επανάληψης Εντολή while Εντολή for.
Η ΓΛΩΣΣΑ C ΜΑΘΗΜΑ 2.
Διδάσκων: Παύλος Παυλικκάς1 Ολυμπιάδα Πληροφορικής Recursion - Αναδρομή.
1 Ολυμπιάδα Πληροφορικής Μάθημα 7. 2 Στόχοι μαθήματος Δημιουργία συναρτήσεων από το χρήστη Δομή προγράμματος με συναρτήσεις Συναρτήσεις και παράμετροι.
Ολυμπιάδα Πληροφορικής
Ολυμπιάδα Πληροφορικής
ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ Is-like-a inheritance. Θεματολόγιο Κληρονομικότητα Παράδειγμα Κληρονομικότητα – Βελτιωμένο Παράδειγμα Ενθυλάκωση : public – private -
1 Ολυμπιάδα Πληροφορικής Μάθημα 5. 2 Στόχοι μαθήματος Πίνακες 2 διαστάσεων.
ΜΑΘΗΜΑ: ΣΧΕΔΙΑΣΗ ΑΛΓΟΡΙΘΜΩΝ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Κυριακή, 11 Ιανουαρίου 2015Κυριακή, 11 Ιανουαρίου 2015Κυριακή, 11 Ιανουαρίου 2015Κυριακή, 11 Ιανουαρίου.
ΣΤΟΙΧΕΙΑ ΤΗΣ ΓΛΩΣΣΑΣ C++ Και ομοιότητες και διαφορές με την C.
ΜΑΘΗΜΑ: ΜΕΤΑΓΛΩΤΤΙΣΤΕΣ ΔΙΔΑΣΚΟΝΤΕΣ: Π. ΚΑΤΣΑΡΟΣ Τρίτη, 31 Μαρτίου 2015Τρίτη, 31 Μαρτίου 2015Τρίτη, 31 Μαρτίου 2015Τρίτη, 31 Μαρτίου 2015Τμ. Πληροφορικής,
ΗΥ150 – ΠρογραμματισμόςΚώστας Παναγιωτάκης ΗΥ-150 Προγραμματισμός Αρχεία.
ΜΑΘΗΜΑ: ΜΕΤΑΓΛΩΤΤΙΣΤΕΣ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τμ. Πληροφορικής,
Ταξινόμηση και Αναζήτηση
ΜΑΘΗΜΑ: ΜΕΤΑΓΛΩΤΤΙΣΤΕΣ ΔΙΔΑΣΚΟΝΤΕΣ: Π. ΚΑΤΣΑΡΟΣ Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τετάρτη, 1 Απριλίου 2015Τμ. Πληροφορικής,
ΜΑΘΗΜΑ: ΣΧΕΔΙΑΣΗ ΑΛΓΟΡΙΘΜΩΝ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Τμ. Πληροφορικής,
ΜΑΘΗΜΑ: ΓΛΩΣΣΑ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ C++ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Τμ.
ΜΑΘΗΜΑ: ΣΧΕΔΙΑΣΗ ΑΛΓΟΡΙΘΜΩΝ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Παρασκευή, 3 Απριλίου 2015Παρασκευή, 3 Απριλίου 2015Παρασκευή, 3 Απριλίου 2015Παρασκευή, 3 Απριλίου 2015Τμ.
ΑΝΑΚΕΦΑΛΑΙΩΣΗ 26 Οκτωβρίου Αντικειμενοστρεφής Προγραμματισμός Ένα νέο προγραμματιστικό μοντέλο (paradigm) το οποίο στηρίζεται στις κλάσεις και τα.
ΠΛΗΡΟΦΟΡΙΑΚΑ & ΤΗΛΕΠΙΚΟΙΝΩΝΙΑΚΑ ΣΥΣΤΗΜΑΤΑ 1η Εργασία Μαθήματος Γιώργος Γιαγλής Οικονομικό Πανεπιστήμιο Αθηνών Τμήμα Διοικητικής Επιστήμης & Τεχνολογίας.
ΜΑΘΗΜΑ: ΜΕΤΑΓΛΩΤΤΙΣΤΕΣ ΔΙΔΑΣΚΟΝΤΕΣ: Κ. ΛΑΖΟΣ - Π. ΚΑΤΣΑΡΟΣ Τρίτη, 14 Απριλίου 2015Τρίτη, 14 Απριλίου 2015Τρίτη, 14 Απριλίου 2015Τρίτη, 14 Απριλίου 2015Τμ.
ΣΤΟΙΧΕΙΑ ΤΗΣ ΓΛΩΣΣΑΣ C++ Πέρασμα παραμέτρων, συναρτήσεις δόμησης και αποδόμησης.
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
Υπερφόρτωση Τελεστών (Συνέχεια) Αντικειμενοστραφής Προγραμματισμός.
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
2/28/00epl-1311 Παραδειγματα Aλγοριθμων Αριθμος λεξεων που διαβαστηκαν απο εισοδο Εκτυπωση περιφερειας τετραγωνων με * Υπολογισμος exp(x,n) = 1 + x/1!
ΗΥ 150 – Προγραμματισμός Ξενοφών Ζαμπούλης ΗΥ -150 Προγραμματισμός Αρχεία.
ΗΥ150 – ΠρογραμματισμόςΞ. Ζαμπούλης ΗΥ-150 Προγραμματισμός Αρχεία.
ΛΟΓ201: Τεχνολογία Λογισμικού ΙΙ Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ201:
ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΕΣ ΤΕΧΝΙΚΕΣ Διδάσκοντες:Γιάννης Μαΐστρος Στάθης Ζάχος Νίκος Παπασπύρου
ΗΥ150 – ΠρογραμματισμόςΚώστας Παναγιωτάκης ΗΥ-150 Προγραμματισμός Τύποι Μεταβλητών Τελεστές Βασική Είσοδος/Έξοδος.
Τεχνολογικό Εκπαιδευτικό Ίδρυμα Θεσσαλίας Προγραμματισμός ΗΥ Ενότητα 2: Συναρτήσεις Εισόδου ⁄ Εξόδου. Διδάσκων: Ηλίας Κ Σάββας, Αναπληρωτής Καθηγητής.
Τεχνολογικό Εκπαιδευτικό Ίδρυμα Θεσσαλίας Αντικειμενοστραφής Προγραμματισμός Ι Ενότητα 10: Αφηρημένες τάξεις. Διδάσκων: Νικόλαος Θ Λιόλιος, Καθηγητής.
Πληροφορική 2 Γλώσσες Προγραμματισμού 1. Γλώσσες προγραμματσιμού  Επιτρέπουν την κωδικοποίηση των αλγορίθμων  Η εκτέλεση ενός προγράμματος θα πρέπει.
ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Ευάγγελος Γ. Ούτσιος Θεόδωρος Γ. Λάντζος.
Αντικειμενοστραφής Προγραμματισμός Ι
Διδάσκων: Δρ. Τσίντζα Παναγιώτα
Εργαστηριακό σεμινάριο Χειμερινό εξάμηνο
ΕΦΑΡΜΟΓΕΣ ΥΠΟΛΟΓΙΣΤΩΝ
Ενισχυτική διδασκαλία
Ενότητα 3 : Γλώσσες προγραμματισμού Δρ. Γκόγκος Χρήστος
Ενότητα Εισαγωγή Είναι εύκολη στη χρήση και στην εκμάθηση.
Προγραμματισμός ΗΥ Ενότητα 11: Header Files. Διδάσκων: Ηλίας Κ Σάββας,
Ενισχυτική διδασκαλία
Τεχνολογία και Προγραμματισμός Υπολογιστών
Τεχνολογία και Προγραμματισμός Υπολογιστών
ΣΥΝΑΡΤΗΣΕΙΣ (Functions)
Αρχές Προγραμματισμού (C)
Μεταγράφημα παρουσίασης:

Είσοδος & Έξοδος στη C++ Ι #include <iostream.h> void main() { cout << “Hello, World“ << endl; } Το αρχείο iostream.h πρέπει να περιλαμβάνεται σε κάθε πηγαίο πρόγραμμα που χρησιμοποιεί λειτουργίες ροής εισόδου – εξόδου. Αυτό το αρχείο κεφαλίδας ορίζει μεταξύ άλλων το αντικείμενο cout που αναπαριστά την τυπική έξοδο. Κάθε δεδομένο που στέλνεται στο cout εμφανίζεται στο τερματικό ή στέλνεται σε αρχείο στην περίπτωση ανακατεύθυνσης της τυπικής εξόδου. Στέλνοντας στη ροή εξόδου το αντικείμενο endl τυπώνεται ο χαρακτήρας νέας γραμμής και εκκενώνεται η προσωρινή περιοχή αποθήκευσης της ροής εξόδου (stream buffer). Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Είσοδος & Έξοδος στη C++ ΙΙ Για να σταλούν δεδομένα στη ροή εξόδου χρησιμοποιείται ο τελεστής <<. Μπορούμε να έχουμε αλυσίδα λειτουργιών εξόδου στην ίδια ροή: cout << “The value of pi is approx. “ << 3.14159 << endl; Μπορούν τα δεδομένα αντί για την τυπική έξοδο να σταλούν σε ένα αρχείο. #include <fstream.h> ofstream os(“output.dat”); os << “The value of pi is approx. “ << 3.14159 << endl; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Είσοδος & Έξοδος στη C++ ΙΙΙ Το αρχείο iostream.h ορίζει επίσης την κλάση istream και ένα αντικείμενο cin για ανάγνωση από την τυπική είσοδο (είτε πληκτρολόγιο ή από ανακατευθυνόμενο αρχείο). Ο τελεστής >> χρησιμοποιείται για την ανάγνωση δεδομένων. double x; cin >> x; Για κάθε δεδομένο που διαβάζεται με τον τελεστή >> αγνοούνται τα κενά που προηγούνται. Αν θέλουμε να διαβάσουμε ένα μόνο χαρακτήρα χωρίς να αγνοήσουμε την πιθανότητα του κενού, τότε καλούμε την get. char ch = cin.get(); Μπορούμε αν θέλουμε να «ανιχνεύσουμε» τον επόμενο χαρακτήρα χωρίς να τον καταναλώσουμε από τη ροή εισόδου: Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Είσοδος & Έξοδος στη C++ ΙV double x; char aChar; char ch = cin.peek(); if (isdigit(ch)) cin >> x; else cin >> aChar; Συνάρτηση που ελέγχει αν υπάρχει αποτυχία στην ανάγνωση δεδομένου από τη ροή εισόδου (α) λόγω ασυμφωνίας τύπων ή (β) λόγω τέλους αρχείου:  Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Είσοδος & Έξοδος στη C++ V Στο παρακάτω πρόγραμμα το loop τερματίζει όταν διαβαστεί συμβολοσειρά που δεν είναι αριθμός ή στο τέλος αρχείου. double t = 0; int n = 0; while (!cin.fail()) { double x; cin >> x; if (!cin.fail()) { t += x; n++; } } if (n > 0) cout << “average: “ << t/n <<endl; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Είσοδος & Έξοδος στη C++ VΙ Ανάγνωση από αρχείο: #include <fstream.h> ifstream is(“input.dat”); is >> x; if (is.fail()) . . . .; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Η συνάρτηση main πρωτότυπο της συνάρτησης main: void main (int argc, char* argv[]); ο αριθμός των παραμέτρων πίνακας δεικτών χαρα- κατά την κλήση του προγ/τος κτήρα που αντιστοιχούν στις συμβολοσειρές των παραμέτρων του προγ/τος Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Προγραμματίζετε με assertions!! H macro assert ορίζεται στο assert.h και επιτρέπει των ορισμό συνθηκών που ο έλεγχός τους έχει ως αποτέλεσμα τον εντοπισμό του αριθμού γραμμής όπου παρουσιάζεται κάποιο λάθος χρόνου εκτέλεσης. //#define NDEBUG #include <assert.h> #include <math.h> // . . . y = f(x); #ifndef NDEBUG assert (y>=0); #endif z = sqrt(y); Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) Ι ΚΑΛΗ ΠΡΑΚΤΙΚΗ ΟΡΙΣΜΟΥ ΚΛΑΣΕΩΝ (Η C++ ΔΙΝΕΙ ΚΑΙ ΑΛΛΕΣ ΔΥΝΑΤΟΤΗΤΕΣ) ΔΗΛΩΝΕΤΕ ΤΙΣ ΛΕΙΤΟΥΡΓΙΕΣ (ΣΥΝΑΡΤΗΣΕΙΣ) ΣΤΟ PUBLIC ΜΕΡΟΣ ΤΟΥ ΟΡΙΣΜΟΥ ΤΗΣ ΚΛΑΣΗΣ ΔΗΛΩΝΕΤΕ ΤΑ ΠΕΔΙΑ ΔΕΔΟΜΕΝΩΝ ΣΤΟ PRIVATE ΜΕΡΟΣ ΤΟΥ ΟΡΙΣΜΟΥ ΤΗΣ ΚΛΑΣΗΣ ΓΡΑΦΕΤΕ ΤΗΝ ΥΛΟΠΟΙΗΣΗ ΤΩΝ ΛΕΙΤΟΥΡΓΙΩΝ ΑΜΕΣΩΣ ΜΕΤΑ ΤΟΝ ΟΡΙΣΜΟ ΤΗΣ ΚΛΑΣΗΣ ΠΑΡΑΔΕΙΓΜΑ οι λειτουργίες αυτές δηλώνονται class Mailbox ως public γιατί καλούνται { για αντικείμενα mailbox public: οπουδήποτε μέσα στο πρόγραμμα void add(Message); Message get_current(); void delete_current(); // . . . } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) ΙΙ ΣΤΗ C++ TA ANTIKEIMENA EINAI ΑΠΛΕΣ ΜΕΤΑΒΛΗΤΕΣ ΠΟΥ Ο ΤΥΠΟΣ ΤΟΥΣ ΕΙΝΑΙ Η ΚΛΑΣΗ ΑΠΟ ΤΗΝ ΟΠΟΙΑ ΕΧΟΥΝ ΔΗΜΙΟΥΡΓΗΘΕΙ κώδικας που αφαιρεί ένα ΠΑΡΑΔΕΙΓΜΑ μήνυμα από ένα mailbox Mailbox mbox; και στη συνέχεια το χρη- Message msg; σιμοποιεί msg = mbox.get_current(); msg.play(); ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΜΠΟΡΕΙ ΝΑ ΚΑΛΟΥΝΤΑΙ ΜΕ ΠΑΡΑΜΕΤΡΟΥΣ ΠΑΡΑΔΕΙΓΜΑ mbox.add(msg); Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) ΙΙI ΚΛΗΣΗ ΛΕΙΤΟΥΡΓΙΑΣ ΓΙΑ ΕΝΑ ΑΝΤΙΚΕΙΜΕΝΟ–ΣΥΝΤΑΞΗ: αντικείμενο.λειτουργία(παράμετροι); ΔΗΛΩΣΗ ΠΕΔΙΩΝ ΔΕΔΟΜΕΝΩΝ ΣΤΗΝ ΚΛΑΣΗ: ΠΑΡΑΔΕΙΓΜΑ class Date δηλώνονται στο private μέρος του { ορισμού της κλάσης για να διασφαλι- public: στεί ότι θα είναι προσβάσιμες μόνο // . . . από τις λειτουργίες της κλάσης Date private: και από πουθενά αλλού int _day; λέμε ότι ο ορισμός της κλάσης int _month; δίνει μια μη ολοκληρωμένη πε- int _year; ριγραφή της κατάστασης αντικει } μένων Στην πραγματικότητα το σύνολο των σωστών καταστάσεων των αντικειμένων της Date είναι ένα υποσύνολο του συνόλου των καταστάσεων που περιγράφεται στον ορισμό της κλάσης (πρέπει π.χ. _day <= 31) Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) ΙV Η κλάση Date είναι παρόμοια με τον ορισμό της στη C ως structure struct { int day; int month; int year; }; Παρόλα αυτά τα structures στη C δεν παρέχουν τη δυνατότητα ελέγχου πρόσβασης στα δεδομένα. Αυτά μπορούν να αλλάξουν από οπουδήποτε μέσα στο πρόγραμμα: struct date birthday = {31, 3, 1961}; // . . . birthday.day = birthday.day + 1; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) V Ο αντίστοιχος κώδικας στη C++ απλά δεν θα μεταφραζόταν: Date birthday; birthday._day = birthday._day + 1; //ERROR Αλλαγή ημερομηνίας μπορεί να γίνει στη C++ μόνο με κλήση της κατάλληλης λειτουργίας που έχει γράψει ο συγγραφέας της κλάσης Date. Μπορεί δηλαδή να γίνει μόνο με ελεγχόμενο τρόπο. Πως γράφουμε την υλοποίηση λειτουργιών; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) VΙ Έστω ότι θέλουμε να αλλάξουμε την τιμή μιας ημερομηνίας b με μία άλλη που αντιστοιχεί σε 30 ημέρες μετά. Αυτό γίνεται με την κλήση της b.advance(30); αλλά προφανώς πρέπει να έχει δηλωθεί και η κατάλληλη συνάρτηση στον ορισμό της κλάσης class Date { public: void advance(int nday); // . . . }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) VΙI και στη συνέχεια ακολουθεί η υλοποίηση της συνάρτησης τελεστής εμβέλειας void Date::advance(int nday) {//μετατροπή σε Ιουλιανή ημερομηνία long j = dat2jul(_day, _month, _year); //πρόσθεση n ημερών j += nday; //μετατροπή από Ιουλιανή ημερομηνία jul2dat(j, _day, _month, _year); } Ο τελεστής εμβέλειας χρησιμοποιείται για να καθορίσει σε ποια κλάση ανήκει η λειτουργία advance Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) VΙIΙ ΤΟ ΣΗΜΑΝΤΙΚΟ ΔΕΝ ΕΙΝΑΙ ΟΙ ΛΕΠΤΟΜΕΡΕΙΕΣ ΤΗΣ ΥΛΟΠΟΙΗΣΗΣ ΑΛΛΑ ΤΟ ΓΕΓΟΝΟΣ ΟΤΙ ΜΕ ΤΗΝ ΚΛΗΣΗ ΤΗΣ Η ΣΥΝΑΡΤΗΣΗ advance ΑΛΛΑΖΕΙ ΤΙΣ ΤΙΜΕΣ ΤΩΝ _day, _month, _year. ΠΟΙΕΣ ΤΙΜΕΣ ΟΜΩΣ ΤΕΛΙΚΑ ΑΛΛΑΖΕΙ ΑΝ ΛΑΒΟΥΜΕ ΥΠΟΨΗ ΟΤΙ ΜΠΟΡΕΙ ΝΑ ΥΠΑΡΧΟΥΝ ΠΟΛΛΑ ΑΝΤΙΚΕΙΜΕΝΑ Date; Η ΣΥΝΑΡΤΗΣΗ ΑΛΛΑΖΕΙ ΤΙΣ ΤΙΜΕΣ ΠΟΥ ΑΝΗΚΟΥΝ ΣΤΟ ΑΝΤΙΚΕΙΜΕΝΟ ΓΙΑ ΤΟ ΟΠΟΙΟ ΚΑΛΕΙΤΑΙ Η ΛΕΙΤΟΥΡΓΙΑ: b.advance(30); ΣΤΗ C++ ΠΑΝΤΑ ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΕΦΑΡΜΟΖΟΝΤΑΙ ΣΕ ΚΑΠΟΙΟ ΑΝΤΙΚΕΙΜΕΝΟ ΠΟΥ ΟΥΣΙΣΤΙΚΑ ΑΠΟΤΕΛΕΙ ΤΗΝ ΥΠΟΝΟΟΥΜΕΝΗ ΠΑΡΑΜΕΤΡΟ ΤΗΣ ΛΕΙΤΟΥΡΓΙΑΣ. ΜΙΑ ΛΕΙΤΟΥΡΓΙΑ ΟΜΩΣ ΜΠΟΡΕΙ ΝΑ ΕΧΕΙ ΚΑΙ ΦΑΝΕΡΕΣ ΠΑΡΑΜΕΤΡΟΥΣ ΚΑΙ ΣΤΟ ΠΑΡΑΔΕΙΓΜΑ ΜΑΣ ΜΙΑ ΤΕΤΟΙΑ ΕΙΝΑΙ ΤΟ 30. ΣΤΗ C++ ΟΙ ΠΡΟΓΡΑΜΜΑΤΙΣΤΕΣ ΑΠΟΚΑΛΟΥΝ ΤΙΣ ΛΕΙΤΟΥΡΓΙΕΣ ΣΥΝΑΡΤΗΣΕΙΣ ΜΕΛΗ ΚΑΙ ΤΑ ΠΕΔΙΑ ΔΕΔΟΜΕΝΩΝ ΤΑ ΑΠΟΚΑΛΟΥΝ ΔΕΔΟΜΕΝΑ ΜΕΛΗ. Ο ΤΕΛΕΣΤΗΣ . ΧΡΗΣΙΜΟΠΟΙΕΙΤΑΙ ΓΙΑ ΠΡΟΣΒΑΣΗ ΕΙΤΕ ΣΤΙΣ ΣΥΝΑΡΤΗΣΕΙΣ ΜΕΛΗ ΕΙΤΕ ΣΤΑ ΔΕΔΟΜΕΝΑ ΜΕΛΗ. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) ΙX CONSTANT ΛΕΙΤΟΥΡΓΙΕΣ class Date { public: void advance(int); void print() const; // . . . }; σημαίνει ότι η συγκεκριμένη λειτουργία δεν αλλάζει την κατάσταση του αντικειμένου αλλά χρησιμοποιείται μόνο για πρόσβαση στα δεδομένα του void Date::print() const { // . . . } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) X ΣΥΝΑΡΤΗΣEIΣ ΑΠΛΗΣ ΠΡΟΣΠΕΛΑΣΗΣ ΠΕΔΙΩΝ ΔΕΔΟΜΕΝΩΝ class Date { public: int month() const; // . . . private: int _day; int _month; είναι συναρτήσεις που απλά int _year; επιστρέφουν την τιμή μιας // . . . private μεταβλητής }; int Date::month() const { return _month; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XI Για το συγγραφέα της κλάσης είναι κάποιος επιπλέον κόπος η συγγραφή τόσο του private δεδομένου μέλους όσο και της αντίστοιχης public συνάρτησης προσπέλασης της τιμής του. Για τον προγραμματιστή που χρησιμοποιεί την κλάση αντί να γράψει d._month γράφει d.month(). Το σημαντικό είναι ότι με αυτόν τον τρόπο η τιμή του δεδομένου μέλους έχει γίνει read only για το υπόλοιπο πρόγραμμα εκτός της κλάσης. Σε περίπτωση λάθους δε χρειάζεται να ερευνηθεί όλο το πρόγραμμα, αλλά μόνο οι συναρτήσεις της κλάσης. H C++ απαιτεί ένα πεδίο δεδομένων να έχει διαφορετικό όνομα από τη συνάρτηση προσπέλασης και γι΄ αυτό το λόγο χρησιμοποιείται το _. Γράφουμε δηλαδή _month για να διακρίνεται από το month(). Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XIΙ ΣΥΝΑΡΤΗΣEIΣ ΓΙΑ ΑΛΛΑΓΗ ΠΕΔΙΩΝ ΔΕΔΟΜΕΝΩΝ void Date::set_month(int m) { if (1<=m && m<=12) _month = m; } Η συνάρτηση set_month δεν δηλώνεται ως const για να μπορεί να αλλάξει τιμή δεδομένου μέλους. Ονομάζεται συνάρτηση αλλαγής δεδομένου μέλους. Όταν χρησιμοποιούμε συναρτήσεις προσπέλασης και αλλαγής πεδίων δεδομένων, αν χρειαστεί να γίνουν αλλαγές στη δομή της κλάσης τότε ο αλλαγές αυτές επηρεάζουν μόνο τις δύο αυτές κατηγορίες συναρτήσεων, που εύκολα μπορούμε να εντοπίσουμε και δεν επηρεάζουν όλο το υπόλοιπο πρόγραμμα. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XIΙΙ Οι συναρτήσεις αλλαγής πεδίων δεδομένων μπορούν να κάνουν έλεγχο για λάθος τιμές. Έτσι, θα μπορούσε για παράδειγμα στην κλήση b.set_month(13) να γίνει ο σχετικός έλεγχος για λάθος τιμή κάτι που δεν είναι εφικτό αν απλά γράφαμε b._month=13. Το παράδειγμα της κλάσης Date είναι μια καλή περίπτωση κλάσης στην οποία δεν είναι καλή ιδέα να ορίσουμε συναρτήσεις αλλαγής τιμής για κάθε ένα δεδομένο μέλος. Θεωρείστε τις κλήσεις: d.set_day(31); d.set_month(3); d.set_year(1961); Αν η προηγούμενη τιμή του d ήταν 1 Φεβρουαρίου, τότε η κλήση της πρώτης συνάρτησης θέτει στο αντικείμενο d την μη επιτρεπτή τιμή 31 Φεβρουαρίου. Αυτό σημαίνει ότι θα είχαμε καλύτερο έλεγχο της ορθότητας της κατάστασης των αντικειμένων Date αν η συνάρτηση αλλαγής ήταν μία και η κλήση της είχε τη μορφή d.set_date(31,3,1961); Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XIV ΣΥΝΑΡΤΗΣEIΣ INLINE Αν μας ενδιαφέρει η ταχύτητα εκτέλεσης και η συνάρτηση που θέλουμε να γράψουμε είναι απλή τότε μπορούμε να τη δηλώσουμε ως inline π.χ. inline int square(int x) {return x*x;} Αυτή η δήλωση θα έχει ως αποτέλεσμα να μεταφράζει ο μεταγλωττιστής το square(expr) απευθείας σε expr*expr υπό τον όρο ότι πρόκειται για απλή έκφραση χωρίς παράπλευρες επιπτώσεις (π.χ. αλλαγή διεύθυνσης μνήμης). Αν η τιμή της έκφρασης είναι προσωρινά αποθηκευμένη στην temp τότε γίνεται απευθείας υπολογισμός της temp*temp. Έχουμε πιο αποδοτική εκτέλεση κώδικα. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XV ΣΥΝΑΡΤΗΣEIΣ INLINE inline int Date::month() const {return _month;} Στην περίπτωση της παραπάνω δήλωσης η κλήση d.month() μεταφράζεται ως d._month, δηλαδή έχουμε απευθείας προσπέλαση στο πεδίο δεδομένων και έτσι παράγεται ποιο αποδοτικός κώδικας. Οι inline συναρτήσεις προστατεύουν την κατάσταση των αντικειμένων της κλάσης και ταυτόχρονα αποφεύγουν το overhead που συνεπάγεται οι πολλές κλήσεις συναρτήσεων. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XVΙ ΣΥΝΑΡΤΗΣEIΣ INLINE Εναλλακτικός τρόπος ορισμού inline συναρτήσεων: class Date { public: int day() const {return _day;} // . . . private: int _day; }; Γενικά ο παραπάνω τρόπος ορισμού δεν θεωρείται μια καλή πρακτική. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XVΙΙ PRIVATE ΣΥΝΑΡΤΗΣΕΙΣ Αρκετά συχνά χρειάζεται να δηλώσουμε private συναρτήσεις, που χρησιμοποιούνται π.χ. Στην υλοποίηση άλλων συναρτήσεων της κλάσης. class Date { public: // . . . private: Bool is_leap_year() const; int _day; }; Σίγουρα η υλοποίηση τέτοιων συναρτήσεων επηρεάζεται από τη δομή της κλάσης, αν όμως η δομή αυτή αλλάξει τότε οι private συναρτήσεις μπορεί και να μη χρειάζονται με τη νέα δομή ή πρέπει να ξαναγραφυτούν. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ορισμός Κλάσης (Τάξης) XVΙΙΙ ΔΙΚΑΙΩΜΑ ΠΡΟΣΠΕΛΑΣΗΣ ΣΕ ΔΙΑΦΟΡΕΤΙΚΑ ΣΤΙΓΜΙΟΤΥΠΑ ΚΛΆΣΗΣ Στη C++ οι συναρτήσεις μέλη έχουν το δικαίωμα προσπέλασης στα ιδιωτικά μέλη κάθε αντικειμένου της κλάσης πράγμα που δεν ισχύει με όλες τις αντικειμενοστρεφείς γλώσσες προγραμματισμού. ΠΑΡΑΔΕΙΓΜΑ int Date::compare(Date b) const { int d = _year – b._year; if (d != 0) return d; d = _month – b._month; return _day – b.d_day; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δομητές (Constructors) I Οι ΔΟΜΗΤΕΣ είναι ειδικές συναρτήσεις που ΚΑΛΟΥΝΤΑΙ ΑΥΤΟΜΑΤΑ κατά τη δημιουργία των αντικειμένων. Οι δομητές ΈΧΟΥΝ ΤΟ ΙΔΙΟ ΟΝΟΜΑ ΜΕ ΤΟ ΌΝΟΜΑ ΤΗΣ ΚΛΑΣΗΣ. class Date { public: Date(int d, int m, int y); // . . . }; Date::Date(int d, int m, int y) : _day(d), _month(m), _year(y) { } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δομητές (Constructors) II Οι ΔΟΜΗΤΕΣ αρχικοποιούν τα πεδία δεδομένων του αντικειμένου. Ο συμβολισμός _day(d) είναι ισοδύναμος με την ανάθεση _day = d. Επειδή δεν απαιτείται κάτι άλλο από το δομητή το σώμα της συνάρτησης δεν περιέχει κάποια επιπλέον εντολή. Επίσης, οι δομητές δεν επιστρέφουν τιμές. Ο δομητής του παραδείγματος καλείται αυτόματα με τη δήλωση ενός αντικειμένου date: Date d(31, 3, 1961); ΔΙΑΦΟΡΕΣ ΔΟΜΗΤΩΝ ΑΠΟ ΤΙΣ ΥΠΟΛΟΙΠΕΣ ΣΥΝΑΡΤΗΣΕΙΣ Ο δομητής καλείται μόνο μία φορά κατά τη δημιουργία του αντικειμένου. Δεν μπορεί να κληθεί δεύτερη φορά για να «επαναρχικοποιήσει» το αντικείμενο Ο δομητής δεν μπορεί να κληθεί για ένα ήδη υπαρκτό αντικείμενο Ο δομητής δεν μπορεί να κληθεί φανερά όπως οι άλλες συναρτήσεις. Καλείται αυτόματα από τη C++ κατά τη δήλωση του αντικειμένου. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δομητές (Constructors) III Μεγάλο πλεονέκτημα των ΔΟΜΗΤΩΝ είναι το ότι η ύπαρξή τους απομακρύνει την πιθανότητα μη αρχικοποιημένων μεταβλητών. Αν οριστεί ΔΟΜΗΤΗΣ αποκλείεται να οριστούν αντικείμενα τα οποία δεν θα αρχικοποιούνται. έτσι αν έχει δηλωθεί η Date(int, int, int) τότε η Date d; είναι λάθος Στις κλάσεις μπορεί να ορίζονται περισσότεροι από ένας δομητές αλλά μόνο ένας από αυτούς θα είναι ο πρoκαθορισμένος (default) Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δομητές (Constructors) IV class Date { public: Date(); Date(int d, int m, int y=0); Date(String); // . . . }; Date::Date(int d, int m, int y) : _day(d), _month(m), _year(y) { if (_year == 0) _year = current year} Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ανώνυμα αντικείμενα Οι δομητές μπορούν να χρησιμοποιηθούν στη δημιουργία αντικειμένων που χρησιμοποιούνται σε υπολογισμούς και μετά δεν μας χρειάζονται: όπως θα γράφαμε στη C int y = x + 10; μπορούμε στη C++ να γράψουμε Date d = Date(31, 3, 1961).advance(x); Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δομητές για αντικείμενα μέλη αντικειμένων Όλα τα αντικείμενα μιας κλάσης πρέπει να δημιουργηθούν ακόμη και αυτά που περιλαμβάνονται ως μέλη σε άλλες κλάσεις. Employee::Employee(String n, int hd, int hm, int hy) : _name(n), _hiredate(hd, hm, hy) { } Ο δομητής αυτός περνάει παραμέτρους στους δομητές των υποαντικειμένων. Τα πεδία που δεν αναφέρονται ρητά στη λίστα αρχικοποίησης όπως π.χ. το _address αρχικοποιούνται από τον προκαθορισμένο δομητή της κλάσης τους. Τα πεδία που ανήκουν σε κλάση που δεν έχει προκαθορισμένο δομητή πρέπει να αρχικοποιηθούν ρητά, αλλιώς ο μεταγλωττιστής θα βγάλει λάθος. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ο καλός προγραμματιστής . . . Κάνει πάντα τα δεδομένα μέλη private Τα πεδία δεδομένων προτιμάει να είναι κλάσεις και όχι απλοί τύποι παράδειγμα κακής σχεδίασης: class Emplyee { public: // . . . private: String _lname; String _fname; char _middle_initial; String _street; String _city; String _state; long _zip; }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ο καλός προγραμματιστής . . . παράδειγμα καλής σχεδίασης class Name { public: // . . . private: String _lname; String _fname; char _middle_initial; }; class Address class Employee { { public: public: // . . . // . . . private: private: String _street; Name _name; String _city; Address _address; String _state; Date _hiredate; long _zip; // . . . // . . . }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ο καλός προγραμματιστής . . . Δεν είναι απαραίτητες συναρτήσεις προσπέλασης και αλλαγής τιμής για όλα τα πεδία. Να δηλώνονται οι συναρτήσεις προσπέλασης ως const. Να υιοθετείται ένα standard στυλ ορισμού κλάσεων για να επιτυγχάνεται ικανοποιητική αναγνωσιμότητα. Π.χ. βάζουμε πρώτα το public μέρος, μετά το private μέρος, στο public μέρος αναφέρουμε πρώτα τους δομητές, μετά τις συναρτήσεις αλλαγής τιμής και τέλος τις συναρτήσεις προσπέλασης τιμής και στο private μέρος βάσουμε πρώτα τις συναρτήσεις και μετά τα δεδομένα μέλη Δεν παραλείπει ποτέ να δηλώσει έναν προκαθορισμένο δομητή Δημιουργεί όλα τα υποαντικείμενα πριν από το σώμα του δομητή. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κληρονομικότητα Ι Παράδειγμα class Point { public: Point(double x=0, double y=0); void move(int dx, int dy); void scale(Point center, double scalefactor); double x() const; double y() const; void plot(GraphicsContext&) const; void print(ostream&) const; // . . . private: double _x; double _y;} Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κληρονομικότητα ΙI class Polygon { public: Polygon(int); void set_vertex(int i, Point p); void move(double dx, double dy); void scale(Point center, double s); void plot(GraphicsContext& gc) const; Point vertex(int) const; // . . . private: Array<Point> _vertex; }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κληρονομικότητα ΙII class Triangle : public Polygon { public: Triangle(Point, Point, Point); }; βασική κλάση από την οποία κληρονομεί παράγωγη κλάση Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κληρονομικότητα ΙII Triangle::Triangle(Point a, Point b, Point c) : Polygon(3) { set_vertex(1,a); set_vertex(2, b); set_vertex(3, c); }; Η παράγωγη κλάση μπορεί να κληρονομήσει τη συνάρτηση B::f() χωρίς αλλαγή. Η παράγωγη κλάση μπορεί να αντικαταστήσει την B::f() με τη συνάρτηση D::f() που θα κάνει μια διαφορετική λειτουργία. Η παράγωγη κλάση μπορεί να επεκτείνει την B::f() με την D::f() να καλεί την B::f() και να κάνει και κάποιες επιπλέον λειτουργίες. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κληρονομικότητα ΙV Επέκταση συνάρτησης – παράδειγμα void ScalableText::scale(Point center, double s) { Text::scale(center, s); _size = _size * s; } Αντικατάσταση συνάρτησης - παράδειγμα class Triangle : public Polygon { public: Triangle(Point, Point, Point); void print(ostream& os) const; }; void Triangle::print(ostream& os) const { . . . . . . . . . Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Πολλαπλή κληρονομικότητα Ι //Παράδειγμα πολλαπλής κληρονομικότητας #include <graphics.h> class Circle { int X_center, Y_center; int radius; public: Circle(int x, int y, int r=20){ X_center=x; Y_center=y; radius=r; } void SetCenter(int x, int y){ void SetRadius(int r){ radius=r;} int GetRadius(){ return radius; } int GetXCenter(){ return X_center; int GetYCenter(){ υπερφόρτωση return Y_center; τελεστή ++ void Paint(){ circle(X_center, Y_center, radius); void operator++(){ radius++; X_center++; Y_center++; }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Πολλαπλή κληρονομικότητα ΙΙ //Παράδειγμα (ΣΥΝΕΧΕΙΑ) enum COLORS { BLACK, BLUE, GREEN, CYAN, ..., WHITE}; class Color { COLORS color; public: Color(COLORS c=BLACK){ color=c; } COLORS GetCol(){ return color; void SetCol(COLORS c){ COLORS operator++(){ color= COLORS((color+1)%getmaxcolor()); }; class ColorCircle:public Circle, Color { public: ColorCircle(int x, int y, int r=20, COLORS c=RED): Circle(x, y, r), Color(c); {} void Paint(){ setcolor(GetCol()); Circle::Paint(); } }; Circle Color ColorCircle Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Πολλαπλή κληρονομικότητα ΙΙI A A class A; class B1: public A; class B2: public A; class C: public B1, public B2; B1 B2 Ο μεταγλωττιστής δημιουργεί δύο αντίγραφα της κλάσης A. Πρόβλημα: αν στην κλάση A υπάρχει ο ορισμός public: int data; τότε για να προσπελασθεί η data μέσα από τη C θα πρέπει να αναφερθεί ως B1::data, αλλιώς η έκφραση θα είναι ασαφής C Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Πολλαπλή κληρονομικότητα ΙV A class A; class B3: virtual public A; class B4: virtual public A; class C: public B3, public B4; B3 B4 ΠΑΡΑΔΕΙΓΜΑΤΑ: D Person Person Person Professor Author Man Woman Professor-Author Married Couple Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Σχέση κληρονομικότητας Ένα αντικείμενο κλάσης A έχει ένα αντικείμενο κλάσης Β. Το αντικείμενο κλάσης Β δηλώνεται ως μέλος της κλάσης Α. Ένα αντικείμενο κλάσης Β είναι κλάσης Α. Η κλάση Β κληρονομεί από την κλάση Α. ΠΑΡΑΔΕΙΓΜΑΤΑ: Ένα τετράγωνο είναι παραλληλόγραμμο. Η γενέθλια ημερομηνία είναι μία ημερομηνία. Ένα άτομο έχει μία διεύθυνση και μία γενέθλια ημερομηνία. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κανόνες συμβατότητας τύπων I Δύο μεταβλητές είναι συμβατές κατά τύπο αν το όνομα των τύπων και των δύο είναι το ίδιο. Εξαίρεση: ένας δείκτης σε υπερκλάση είναι συμβατός με οποιοδήποτε δείκτη σε κλάση που προέρχεται από αυτή (υποκλάση). #include <iostream.h> void main() { typedef struct { char first; char second;} twoChars; twoChars state1; twoChars state2; state1.first=‘M’; state1.second=‘N’; state2=state1; //σωστό: οι μεταβλητές είναι του ίδιου τύπου state2.second++; cout << “Original structure: “ << state1.first << state1.second << endl << “Changed structure: ” << state2.first << state2.second << endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κανόνες συμβατότητας τύπων IΙ #include <iostream.h> void main() { struct { char first; char second;} state1; char second;} state2; state1.first=‘M’; state1.second=‘N’; state2=state1; //λάθος: οι μεταβλητές δεν είναι του ίδιου τύπου state2.second++; cout << “Original structure: “ << state1.first << state1.second << endl << “Changed structure: ” << state2.first << state2.second << endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κανόνες συμβατότητας τύπων IΙΙ #include <iostream.h> void main() { struct { char first; char second;} state1, state2; state1.first=‘M’; state1.second=‘N’; state2=state1; //σωστό: οι μεταβλητές είναι του ίδιου τύπου state2.second++; cout << “Original structure: “ << state1.first << state1.second << endl << “Changed structure: ” << state2.first << state2.second << endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κανόνες συμβατότητας τύπων IV class TwoChars { char first; char second; public: TwoChars(char f,char s){ first=f; second=s; } }; class StateCode { StateCode(char f,char s){ void main() { StateCode* pState1; TwoChars* pState2; pState1=new StateCode(‘C’, ‘A’); pState2=new TwoChars(‘H’, ‘I’); pState2=pState1; // ΛΑΘΟΣ pState1=pState2; // ΛΑΘΟΣ } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Κανόνες συμβατότητας τύπων V class TwoChars { char first; char second; public: TwoChars(char f,char s){ first=f; second=s; } }; class StateCode:public TwoChars { StateCode(char f,char s): TwoChars(f, s) {} void main() { StateCode* pState1; TwoChars* pState2; pState1=new StateCode(‘C’, ‘A’); pState2=new TwoChars(‘H’, ‘I’); pState2=pState1; // ΣΩΣΤΟ pState1=pState2; // ΛΑΘΟΣ pState2=new StateCode(‘A’, ‘R’); } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Δυναμική αντιστοίχιση (dynamic binding) - Παράδειγμα #include <iostream.h> class Person { protected: char* name; public: Person(char* n){ name=n; } virtual void Print() { cout <<“My name is” <<name<<endl; }; class Foreigner:public Person { Foreigner(char* n):Person(n) { void Print() { cout <<“Il mio nome e” <<name<<endl; } }; void main() { Person* man; Person* woman;//ίδιος τύπος με την man man=new Person(“John”); woman=new Foreigner(“Paola”); //!!! cout <<“Prints the name of the man:” <<endl; man->Print(); //καλεί από την Person cout<<“Prints the name of the woman:” woman->Print(); //καλεί από τη Foreigner Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Μετατροπή Δεδομένων Ι Τι γίνεται όταν έχουμε εντολή απόδοσης τιμής var1=var2 και οι μεταβλητές που βρίσκονται αριστερά και δεξιά του τελεστή = είναι διαφορετικού τύπου; Αυτόματη μετατροπή: μετατροπές που γίνονται αυτόματα από το μεταγλωττιστή σύμφωνα με τους κανόνες μετατροπής δεδομένων της γλώσσας. Παραδείγματα: από int σε float, από float σε double κ.α. Κατ΄απαίτηση προσαρμογή: ο προγραμματιστής ορίζει τον τύπο στον οποίο θα γίνει η μετατροπή με τον τελεστή προσαρμογής (casting) Παράδειγμα μετατροπής μεταξύ βασικών τύπων: var1=int(var2); Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Μετατροπή Δεδομένων ΙΙ Μετατροπή μεταξύ δεδομένων βασικών τύπων και αντικειμένων (κλάσεων οριζόμενων από το χρήστη #include <iostream.h> const float MTF=3.280833; class Distance { private: int feet; float inches; public: Distance() {feet=0; inches=0.0;} Distance(float meters) { float fltfeet=MTF*meters; feet=int(fltfeet); inches=12*(fltfeet-feet);} Distance(int ft,float in) { feet=ft; inches=in;} void getdist() { cout<<“\n Δώσε τα πόδια: ”; cin>>feet; cout<<“\n Δώσε τις ίντσες: ”; cin>>inches; } void showdist(){ cout<<feet<<“/’-”<<inches <<‘\”’;} operator float() { float fracfeet=inches/12; fracfeet+=float(feet); return fracfeet/MTF;} }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Μετατροπή Δεδομένων ΙΙI void main() { Distance dist1=2.35; //χρήση δομητή για τη μετατροπή //μέτρων σε Distance cout<<“\ndist1 =”; dist1.showdist(); dist1=1.00; //χρήση δομητή με ένα όρισμα cout<<“\ndist1=”; dist1.showdist(); Distance dist2(5,10.25); //χρήση δομητή με δύο ορίσματα float mtrs=float(dist2); //χρήση συνάρτησης μετατροπής για cout<<“\ndist2=“<<mtrs<<“ μέτρα”; //μετατροπή distance σε μέτρα mtrs=dist1; //έχουμε μετατροπή τύπου επίσης με cout<<“\ndist1=“<<mtrs<<“ μέτρα”; //χρήση της συνάρτησης μετατροπής } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Μετατροπή Δεδομένων ΙV Μετατροπή τύπου Μέλος στον Μέλος στον τύπο προέλευσης τύπο προορισμού Βασικός σε βασικό (από το μεταγλωττιστή) Βασικός σε κλάση ΔΕΝ ΥΠΑΡΧΕΙ Δομητής Κλάση σε βασικό Συνάρτηση μετατροπής ΔΕΝ ΥΠΑΡΧΕΙ Κλάση σε κλάση Συνάρτηση μετατροπής Δομητής Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Έλεγχος ισοδυναμίας τύπων Για να λειτουργεί χρειάζεται η κλάση να έχει τουλάχιστο μία virtual συνάρτηση. Shape* s; if (typeid(s) == typeid(Rectangle*)) // s points to a Rectangle object else // s points to an object of some other class Στις παλιότερες εκδόσεις της C++ χρειάζεται να δημιουργήσετε το δικό σας μηχανισμό ελέγχου ισοδυναμίας τύπων (συναρτήσεις που να επιστρέφουν κάποια ένδειξη του τύπου του αντικειμένου). Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων Ι Στον αντικειμενοστρεφή προγραμματισμό χρησιμοποιούμε ιεραρχίες κλάσεων για: την περιγραφή μιας κατάταξης αντικειμένων σε κατηγορίες περιγράφουμε τα αντικείμενα σε σχέση με τις μεταξύ τους ομοιότητες και διαφορές αποφεύγοντας την πλήρη περιγραφή, όπου σε αρκετές περιπτώσεις θα υπήρχε επανάληψη κώδικα π.χ. κατηγορίες από τη βιολογία: κλάση ζώα, κλάση φυτά τη δημιουργία παραλλαγών μιας κλάσης, που διαφοροποιούνται σε σχέση με την υλοποίησή τους π.χ. ένας inkject printer μπορεί να κληρονομεί από την κλάση dot-matrix printer, αλλά αντί για ακίδες (αφαιρούνται από την υλοποίηση) διαθέτει μπεκ ψεκασμού την αφαίρεση (γενίκευση) των κοινών στοιχείων ενός αριθμού κλάσεων π.χ. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων ΙΙ Αφαίρεση ή γενίκευση (abstraction) Η περιγραφή ενός αριθμού αντικειμένων διαφορετικών κλάσεων από μία νέα κλάση που θα ενσωματώνει τα κοινά τους χαρακτηριστικά με ένα γενικό τρόπο. Όλα τα κοινά μέλη (δεδομένα, συναρτήσεις) θα περιγράφονται στη γενική κλάση όχημα. Η γενική κλάση που συνήθως αποτελείται από virtual συναρτήσεις παρέχει έτσι μία κοινή διασύνδεση και τη δυνατότητα ομοιόμορφης ονοματολογίας σε όλες τις υποκλάσεις. Φυσικά κάθε συνάρτηση της γενικής κλάσης μπορεί να επανακαθορισθεί στις υποκλάσεις όπως χρειάζεται. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

virtual int pure_function(int number)=0; Ιεραρχίες κλάσεων ΙΙΙ Virtual συναρτήσεις χρησιμοποιήθηκαν και στο παράδειγμα με τη δυναμική αντιστοίχιση (dynamic binding), αλλά τώρα θα χρησιμοποιήσουμε καθαρά virtual συναρτήσεις (pure virtual functions). Η διαφορά είναι ότι οι καθαρά virtual συναρτήσεις δεν μπορούν να κληθούν για αντικείμενα της κλάσης στην οποία ορίζονται, αλλά μόνο για αντικείμενα κλάσεων όπου επανακαθορίζονται. virtual int pure_function(int number)=0; Μια κλάση που έχει τουλάχιστο μία καθαρά virtual συνάρτηση λέγεται κλάση αφαίρεσης (abstract class). Το χαρακτηριστικό των κλάσεων αφαίρεσης είναι ότι δεν μπορούμε παράγουμε αντικείμενα γι αυτές γιατί δεν το επιτρέπει η γλώσσα. Οι κλάσεις αφαίρεσης χρησιμεύουν μόνο ως βάση κληρονομικότητας για τις υποκλάσεις. Παρόλα αυτά οι κλάσεις αφαίρεσης μπορούν να χρησιμοποιούνται ως τύποι δείκτη που ενδεχομένως περνάνε ορίσματα μέσα σε συναρτήσεις. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων ΙV class Printer { public: Printer() {} virtual void Method(char*buffer)=0; virtual int Dpi()=0; }; void function1(Printer pr); //ΛΑΘΟΣ: δεν επιτρέπεται void function2(Printer& pr); //ΣΩΣΤΟ void function3(Printer* pr); //ΣΩΣΤΟ Κάθε κλάση που κληρονομεί από μία κλάση αφαίρεσης και επανακαθορίζονται σε αυτήν όλες οι virtual συναρτήσεις λέγεται ειδική κλάση (concrete class). Τα αντικείμενα των ειδικών κλάσεων μπορούν είτε να χρησιμοποιούνται απευθείας είτε μέσω δείκτη σε κλάση αφαίρεσης, όπως στο παράδειγμα: Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων V #include <stdio.h> #include <iostream.h> class Printer { public: Printer(){} virtual void Method(char*buffer)=0; virtual int Dpi()=0; }; class DotMatrixPrinter:public Printer int nDots; DotMatrixPrinter(int n) { nDots=n; } void Method(char*buffer) { sprintf(buffer,”Dot matrix printer with %d pins”,nDots); int Dpi() { switch(nDots) { case 8: return 150; case 9: return 160; case 24: return 300; default: return 100; }} }; void main() { char description[40]; DotMatrixPrinter dmp(24);//Αντι dmp.Method(description); cout<<description << endl <<“DPI: ”<<dmp.Dpi()<<endl; Printer* pPri; //Δείκτ abstract pPri=new DotMatrixPrinter(9); pPri->Method(description); <<“DPI: ”<< pPri->Dpi() <<endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων VΙ Οι κλάσεις αφαίρεσης είναι πολύ σημαντικές και στον πολυμορφισμό και τη δυναμική αντιστοίχιση. Γενικά είναι προτιμότερο να χρησιμοποιείται κληρονομικότητα από κλάσεις αφαίρεσης παρά από ειδικές κλάσεις. Μία ειδική κλάση ορίζει τη δικιά της αναπαράσταση δεδομένων, που βέβαια δεν πρέπει να δεσμεύει όλες τις υποκλάσεις. Αντίθετα στις κλάσεις αφαίρεσης συνήθως δεν περιλαμβάνουμε δεδομένα ως μέλη ή τουλάχιστο περιλαμβάνουμε μόνο μερικά από αυτά που συμβαίνει να υπάρχουν κοινά σε όλες τις υποκλάσεις. Έτσι, επιτρέπεται στις ειδικές κλάσεις να ορίζουν τα δικά τους ιδιωτικά (private) δεδομένα χωρίς κίνδυνο συγκρούσεων και χωρίς να κληρονομούν άχρηστα δεδομένα άλλων κλάσεων. Η δημιουργία νέων «αφαιρέσεων» δεν είναι απλή υπόθεση αλλά είναι μία τεχνική που πρέπει να καλλιεργήσει ο καλός προγραμματιστής. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων VΙΙ ΣΥΝΤΑΓΕΣ ΓΙΑ ΤΗ ΔΗΜΙΟΥΡΓΙΑ ΕΝΟΣ «ΚΑΛΟΥ» ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΟΥΣ ΠΡΟΓΡ/ΤΟΣ - οι ιεραρχίες κλάσεων πρέπει να είναι περιορισμένες και σε κάποιο ύψος και όχι «ρηχές» και «απλωμένες» - η κλάση στη ρίζα και οι ενδιάμεσες κλάσεις (αν αυτό είναι εφικτό) πρέπει να είναι κλάσεις αφαίρεσης - οι κλάσεις μπορούν να είναι πιο γενικές αν γίνει κατορθωτό να περιορισθεί η χρήση δεδομένων ή η χρήση συγκεκριμένης αναπαράστασης δεδομένων. Αυτό γίνεται αν προσπελαύνονται τα δεδομένα με τη χρήση συναρτήσεων και όχι με απευθείας προσπέλαση. Έτσι, θα μπορεί αν χρειασθεί να αλλαχθεί η αναπαράσταση των δεδομένων με την αλλαγή των συναρτήσεων αφήνοντας ίδιο τον κώδικα όπου χρησιμοποιούνται. - οι κληρονομούσες κλάσεις πρέπει να είναι εξειδικεύσεις Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων VΙΙΙ ΜΙΑ «ΙΔΑΝΙΚΗ» ΙΕΡΑΡΧΙΑ ΚΛΑΣΕΩΝ ΚΛΆΣΗ ΑΦΑΙΡΕΣΗΣ ΕΙΔΙΚΗ ΚΛΑΣΗ Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Ιεραρχίες κλάσεων ΙΧ ΠΑΡΑΔΕΙΓΜΑ ΕΠΕΚΤΑΣΗΣ ΜΙΑΣ ΙΕΡΑΡΧΙΑΣ ΚΛΑΣΕΩΝ Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών Ι Τελεστές στους οποίους μπορεί να γίνει υπερφόρτωση + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> <<= >>= == != <= >= && || ++ -- -> ->* [] () , Στους τελεστές + - * & μπορούμε να κάνουμε υπερφόρτωση τόσο στη μοναδιαία (ένας τελεσταίος) όσο και στην δυαδική τους μορφή (δύο τελεσταίοι) Παράδειγμα υπερφόρτωσης δυαδικής μορφής τελεστή Vector Vector::operator-(Vector b) const Παράδειγμα υπερφόρτωσης μοναδιαίας μορφής τελεστή Vector Vector::operator-() const { return Vector(-x(), -y()); } Χρήση δυαδικού τελεστή: a – b Xρήση μοναδιαίου τελεστή: -a Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών ΙI Τελεστές στους οποίους δεν μπορεί να γίνει υπερφόρτωση . .* :: ?: Δεν μπορούμε να δημιουργήσουμε νέους τελεστές Μία συνάρτηση υπερφόρτωσης πρέπει να έχει τουλάχιστο ένα όρισμα (implicit ή explicit) τύπου κλάσης. Δεν μπορούμε να επαναπροσδιορίσουμε τελεστές που εφαρμόζονται μόνο σε αριθμητικούς τελεσταίους (int, double, . . .) ή μόνο σε δείκτες (char*, X*, . . .) Η προτεραιότητα και η προσεταιριστικότητα των υπερφορτωμένων τελεστών παραμένει η ίδια με αυτή που διαθέτουν στην προκαθορισμένη τους μορφή Παράδειγμα: Fraction Fraction::operator^(int) const; ΠΡΟΣΟΧΗ ΣΤΗΝ ΠΡΟΤΕΡΑΙΟΤΗΤΑ: το a^2+1 θα εκτελεστεί ως a^(2+1) Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών ΙII Χρειάζεται ιδιαίτερη προσοχή στην υπερφόρτωση των τελεστών ++ και – και αυτό γιατί έχουμε και προθεματική μορφή (++x) και επιθεματική μορφή (x++) αυτών των τελεστών. Αν θέλουμε να καλύψουμε και τις δύο περιπτώσεις πρέπει να ορίσουμε δύο συναρτήσεις υπερφόρτωσης Fraction Fraction::operator++(); //prefix inc και Fraction Fraction::operator++(int); //postfix Στην περίπτωση της συνάρτησης υπερφόρτωσης για την επιθεματική εκδοχή το όρισμα int χρησιμοποιείται μόνο για να δείξει ότι πρόκειται για επιθεματική μορφή. Η τιμή που περνάει είναι πάντα 0. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών ΙV class Fraction { public: Fraction(long n = 0, long d = 1); Fraction operator+(Fraction) const; // . . . private: long _num; long _den; }; Fraction::Fraction(long n, long d) : _num(n) _den(d) { } Fraction Fraction::operator+(Fraction b) const { return Fraction(_num * b._den + _den * b._num, _den * b._den); } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών V Στο προηγούμενο παράδειγμα ο constructor Fraction f = 2; μετατρέπει έναν ακέραιο σε κλάσμα. Το ίδιο γίνεται αυτόματα στην αριθμητική έκφραση Fraction g = f + 2; // g = f.operator+(Fraction(2,1)); Χρειάζεται όμως ιδιαίτερη προσοχή γιατί δεν θα μπορούσαμε να χρησιμοποιήσουμε τη φαινομενικά ισοδύναμη έκφραση 2 + f Αυτό συμβαίνει γιατί ο compiler δεν μπορεί να εκτελέσει τη μετατροπή τύπου Fraction(2).operator+(f) Το υπονοούμενο όρισμα (implicit argument) χρησιμοποιείται αποκλειστικά για επιλογή κλάσης και δεν μπορεί να χρησιμοποιηθεί για να γίνει μετατροπή τύπου. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών VΙ Όπως είδαμε στο προηγούμενο παράδειγμα οι constructors που δέχονται ένα μόνο όρισμα εξυπηρετούν και ως συναρτήσεις μετατροπής. Έτσι ο δομητής Fraction(int) μπορεί αυτόματα να μετατρέψει έναν integer σε fraction(με παρονομαστή 1) και βασικά για αυτόματη μετατροπή τύπων χρησιμοποιούνται τέτοιοι δομητές. Τι γίνεται όμως όταν: Ο τύπος στον οποίο θέλουμε να μετατρέψουμε δεν είναι κλάση; Ο τύπος στον οποίο θέλουμε να μετατρέψουμε είναι κλάση την οποία όμως δεν μπορούμε να αλλάξουμε; Ας θεωρήσουμε την μετατροπή από fractions σε αριθμούς κινητής υποδιαστολής. Επειδή ο τύπος double δεν είναι κλάση δεν μπορούμε να δηλώσουμε δομητή γι΄ αυτόν τον τύπο και έτσι δηλώνουμε έναν τελεστή μετατροπής τύπου Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Υπερφόρτωση Τελεστών VΙΙ ΠΑΡΑΔΕΙΓΜΑ class Fraction { public: // . . . operator double() const; }; Fraction::operator double() cnst { return (double) _num / (double) _den; } Fraction f(1, 4); y = sqrt(f); // μετατρέπεται σε y = sqrt(f.operator double()) Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) Ι Ο λόγος που επιδιώκουμε τη δυνατότητα γενίκευσης μιας κλάσης (ή συνάρτησης) είναι το να μπορούμε να κάνουμε τον ορισμό της χωρίς να προσδιορίσουμε τον τύπο ενός ή περισσοτέρων μελών της (παράμετροι). Έτσι, θα μπορούμε να προσαρμόζουμε την κλάση (συνάρτηση) σε διαφορετικές περιπτώσεις χρήσης της χωρίς να επιβάλλεται να την ξαναγράψουμε. ΠΑΡΑΔΕΙΓΜΑ Πρέπει να γράψουμε τον κώδικα για μια ουρά ή μια στοίβα. Μπορούμε εύκολα να ορίσουμε μια ουρά ακεραίων, αλλά τι γίνεται όταν θέλουμε σε μία ουρά να χρησιμοποιούμε αντικείμενα τύπου date; Κάθε γλώσσα αντιμετωπίζει το παραπάνω πρόβλημα και με διαφορετικό τρόπο. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) ΙΙ Στη Smalltalk όπου ο έλεγχος τύπων γίνεται σε χρόνο εκτέλεσης ο πολυμορφισμός δεν περιορίζεται στις ιεραρχίες των κλάσεων, αλλά κάθε κλάση μπορεί να αντικατασταθεί από μία άλλη. Έτσι, η γενίκευση γίνεται εύκολα. Στη C++ έχουμε έλεγχο τύπων σε χρόνο μεταγλώττισης. Υπάρχουν δύο τρόποι για την επίτευξη γενίκευσης: με χρήση κληρονομικότητας και πολυμορφισμού ορίζοντας κλάση, που χειρίζεται δείκτες σε αντικείμενα με χρήση παραμετροποιήσιμων τμημάτων κώδικα, των επονομαζόμενων templates Η πρώτη μέθοδος (βλ. παράδειγμα παρακάτω) συνοδεύεται από έναν κίνδυνο με την κατ΄ απαίτηση προσαρμογή (casting) που χρειάζεται στην ανάκτηση του τύπου των αντικειμένων που χειρίζεται η κλάση με τους δείκτες. Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) ΙΙΙ class GenericObject {}; //stack.h class Stack { GenericObject* data[50]; int nElements; public: Stack() { nElements=0; } void Push(GenericObject* elem); GenericObject* Pop(); int Number(); int Empty(); }; #include “stack.h” //stack.cpp void Stack::Push(GenericObject* elem) { data[nElements]=elem; nElements++; GenericObject* Stack::Pop() { nElements--; return data[nElements]; } int Stack::Number() { return nElements; int Stack::Empty() { return (nElements==0); #include <iostream.h> //sta_use.cpp #include “stack.cpp” class IntObj:public GenericObject { public: int data; IntObj(int n) { data=n; }; Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) ΙV void main() { Stack genericStack; //εισάγουμε νέα αντικείμενα στη στοίβα genericStack.Push(new IntObj(500)); genericStack.Push(new IntObj(1992)); genericStack.Push(new IntObj(33)); genericStack.Push(new IntObj(1024)); //τυπώνει τα στοιχεία της στοίβας καθώς την αδειάζει: //επειδή η συνάρτηση Pop επιστρέφει δείκτη σε //GenericObject, για να προσπελάσουμε μέλος του //αντικειμένου που βγάλαμε χρειάζεται type casting while(!genericStack.Empty()) cout<<((IntObj*)genericStack.Pop())->data<<endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) V template<class T> //stack.h με template class Stack { T* data[50]; int nElements; public: Stack() { nElements=0; } void Push(T elem); T Pop(); int Number(); int Empty(); }; #include “stack.h” //stack.cpp template<class T> void Stack<T>::Push(T elem) { data[nElements]=elem; nElements++; template<class T> T Stack<T>::Pop() { nElements--; return data[nElements];} int Stack<T>::Number() { return nElements;} int Stack<T>::Empty() { return (nElements==0); } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017

Γενίκευση (genericity) VI #include <iostream.h> //sta_use.cpp #include “stack.cpp” void main() { Stack <int> intStack; //εισάγουμε νέα αντικείμενα στη στοίβα intStack.Push(500); intStack.Push(1992); intStack.Push(33); intStack.Push(1024); while(!intStack.Empty()) cout<<intStack.Pop())<<endl; } Τμ. Πληροφορικής, Α.Π.Θ. Σάββατο, 8 Απριλίου 2017