Αντικειμενοστραφής Προγραμματισμός Θεωρία Παραδείγματα - Προγράμματα 1
ΣΥΝΑΡΤΗΣΕΙΣ Παραδείγματα χρήσης συναρτήσεων ΠΟΛΛΕΣ ΕΝΤΟΛΕΣ ΕΠΙΣΤΡΟΦΗΣ Να γραφτεί ένα πρόγραμμα που να διπλασιάζει ένα ποσό που του δίνει ο χρήστης μεταξύ 0 και 1000. Να ελέγχει εάν το ποσό που εισήχθη είναι μεγαλύτερο από 1000 να βγάζει μήνυμα λάθους. int diplasio(int posogiadiplasiasmo); int main() int apotelesma=0; int posoeisagomeno; cout<<"dose poso metaxy 0 kai 10000 gia na to diplasiaso: "; cin>>posoeisagomeno; cout<<"\nprin kaleso thn diplasio... "; cout<<"\neisagomeno poso: "<<posoeisagomeno<<" Diplasio: "<<apotelesma<<"\n"; apotelesma=diplasio(posoeisagomeno); if (apotelesma==-1) cout<<"\nepistrofh apo thn diplasio...\n"; cout<<"to poso pou edoses einai megalytero apo 10000\n\n"; else cout<< "\nepistrofh apo thn diplasio..."; cout<< "\neisagomeno poso: "<<posoeisagomeno<< " Diplasio: "<<apotelesma<< "\n\n"; return 0; int diplasio(int pragmatiko) if (pragmatiko<=10000) return pragmatiko * 2; else return -1; cout<<"den mporeite na pate edw\n"; Σημ. Η εντολή που βρίσκεται στην τελευταία γραμμή του προγράμματος δεν θα εκτελεστεί γιατί προηγείται αυτής το return -1. 2
ΠΕΡΑΣΜΑ ΟΡΙΣΜΑΤΩΝ ΜΕ ΤΙΜΗ (ΠΑΡΑΜΕΤΡΟΙ ΣΑΝ ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ) Να γραφτεί ένα πρόγραμμα που να κάνει αλλαγή θέσης 2 τιμών τοπικών μεταβλητών χωρίς να επηρεάζονται οι αρχικές μεταβλητές. void swap(int x, int y); int main() int a,b; cout<<"dose a: "<<endl; cin>>a; cout<<"dose b: "<<endl; cin>>b; cout<<"main. Prin to swap, a: "<<a<<" b: "<<b<<"\n"; swap(a,b); cout<<"main. Meta to swap, a: "<<a<<" b: "<<b<<"\n"; return 0; void swap(int x, int y) int temp; cout<<"swap. Prin to swap, x: "<<x<<" y: "<<y<<"\n"; temp=x; x=y; y=temp; cout<<"swap. Meta to swap, x: "<<x<<" y: "<<y<<"\n"; Σύντομη εξήγηση του προγράμματος. Σε αυτό το πρόγραμμα ένα αντίγραφο των τιμών των μεταβλητών a,b περνούν στις x,y. Στην έξοδο έχουμε την αντιστροφή των μεταβλητών x,y χωρίς να επηρεαστούν οι τιμές των μεταβλητών a,b 3
ΥΠΕΡΦΟΡΤΩΣΗ ΣΥΝΑΡΤΗΣΕΩΝ Να γραφτεί ένα πρόγραμμα που να χρησιμοποιεί μία συνάρτηση με υπερφόρτωση ώστε να κάνει τα εξής: I. Να τυπώνει στην οθόνη 50 μηδενικά (0), II. Να τυπώνει στην οθόνη 50 χαρακτήρες που θα καθορίζονται από την κλήση της συνάρτησης και III. Να τυπώνει στην οθόνη χαρακτήρες που ο χαρακτήρας αλλά και ο αριθμός των χαρακτήρων να καθορίζονται στην κλήση της συνάρτησης. void printfunc(); void printfunc(char ch); void printfunc(char ch, int n); printfunc(); printfunc('/'); printfunc('%',40); void printfunc() int i; for (i=0; i<50; i++) cout << "0"; cout << endl; void printfunc(char ch) int i; for (i=0; i<50; i++) cout << ch; cout << endl; void printfunc(char ch, int n) int i; for (i=0; i<n; i++) cout << ch; cout << endl; 4
ΥΠΕΡΦΟΡΤΩΣΗ ΣΥΝΑΡΤΗΣΕΩΝ (ΜΕ ΠΡΟΕΠΙΛΕΓΜΕΝΑ ΟΡΙΣΜΑΤΑ) Να γραφτεί το προηγούμενο πρόγραμμα που να χρησιμοποιεί μία συνάρτηση με υπερφόρτωση και προεπιλεγμένα ορίσματα - και 50 void printfunc(char ch='-', int n=50); printfunc(); printfunc('/'); printfunc('%',40); void printfunc(char ch, int n) int i; for (i=0; i<n; i++) cout << ch; cout << endl; Σύντομη εξήγηση του προγράμματος. Εδώ το πρόγραμμα θα χρησιμοποιήσει (καλέσει) την συνάρτηση 3 φορές. Την πρώτη φορά το loop που βρίσκεται μέσα στον ορισμό της συνάρτησης θα χρησιμοποιήσει και τα δύο προεπιλεγμένα ορίσματα που βρίσκονται μέσα στο πρωτότυπο. Την δεύτερη φορά θα χρησιμοποιήσει το όρισμα της κλήσης συνάρτησης και το δεξί του πρωτοτύπου και την τρίτη φορά θα χρησιμοποιήσει τα ορίσματα που βρίσκονται στη κλήση της συνάρτησης. 5
ΠΡΟΚΑΘΟΡΙΣΜΕΝΕΣ ΤΙΜΕΣ ΠΑΡΑΜΕΤΡΩΝ Να γραφτεί ένα πρόγραμμα που να υπολογίζει τον όγκο ενός κύβου. Χρησιμοποιούνται προκαθορισμένες τιμές. int ogkoskyvou(int mhkos, int platos = 30, int ypsos = 2); int main() int mhkos = 50; int platos = 20; int ypsos = 5; int ogkos; ogkos = ogkoskyvou(mhkos, platos, ypsos); cout << "1h Klhsh Synarthshs o ogkos einai: " << ogkos << "\n"; ogkos = ogkoskyvou(mhkos, platos); cout << "2h Klhsh Synarthshs o ogkos einai: " << ogkos << "\n"; ogkos = ogkoskyvou(mhkos); cout << "3h Klhsh Synarthshs o ogkos einai: " << ogkos << "\n"; return 0; ogkoskyvou(int mhkos, int platos, int ypsos) return (mhkos * platos * ypsos); Σύντομη εξήγηση του προγράμματος. Εδώ το πρόγραμμα θα χρησιμοποιήσει (καλέσει) την συνάρτηση 3 φορές με διαφορετικές κάθε φορά παραμέτρους κατά την κλήση. Την πρώτη φορά θα υπολογιστεί ο όγκος χρησιμοποιώντας τις τιμές των παραμέτρων που έχουν οριστεί μέσα στην main. Την δεύτερη φορά χρησιμοποιώντας τις τιμές δύο εκ των παραμέτρων που έχουν οριστεί μέσα στην main και την τελευταία στη σειρά στο πρωτότυπο και τη Τρίτη φορά χρησιμοποιώντας την τιμή της μιας παραμέτρου που έχει οριστεί μέσα στην main και την 2 η και 3 η κατά σειρά στο πρωτότυπο. 6
ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΗΣ ΑΠΟ ΣΥΝΑΡΤΗΣΗ Να γραφτεί ένα πρόγραμμα που να υπολογίζει εάν ο αριθμός που εισάγει ο χρήστης είναι άρτιος ή περιττός. Εάν δοθεί σαν επιλογή ο αριθμός 0 τότε το πρόγραμμα να τερματίζει. void peritos(int a); void artios(int a); int main() int i; do cout<<"dose enan arithmo (0 gia EXODO): "; cin>>i; peritos(i); while (i!=0); return 0; void peritos(int a) if ((a%2)!=0) cout<<"o arithmos pou edoses einai PERITOS.\n"; else artios(a); void artios(int a) if ((a%2)==0) cout<<"o arithmos pou edoses einai ARTIOS.\n"; else peritos(a); Σύντομη εξήγηση του προγράμματος. Εδώ το πρόγραμμα θα βρει εάν ο αριθμός που εισήχθη είναι άρτιος ή περιττός με την χρήση κλήσης συνάρτησης από συνάρτηση. Η πρώτη συνάρτηση καλείται μέσα στην main. Εκεί ελέγχεται εάν ο αριθμός που εισήχθη είναι το 0 κάτι που προκαλεί το τερματισμό του προγράμματος. Στην πρώτη συνάρτηση (peritos) ελέγχεται εάν το υπόλοιπο της διαίρεσης του αριθμού δεν είναι 0 τότε ο αριθμός είναι περιττός αλλιώς καλείται η δεύτερη συνάρτηση (artios) που ελέγχει με την σειρά της εάν ο αριθμός είναι άρτιος. 7
INLINE ΣΥΝΑΡΤΗΣΕΙΣ Πρόγραμμα που διπλασιάζει 3 φορές διαδοχικά μια τιμή εισόδου με την χρήση INLINE συνάρτησης. inline int Diplasio(int); int main() int timh; cout<<"dose MIA TIMH: "; cin>>timh; cout<<"\ndiadoxikos DIPLASIASMOS TIMHS\n"; cout<<"\narxikh TIMH: "<<timh<<endl; timh=diplasio(timh); cout<<"timh1 (ARXIKH TIMH x 2): "<<timh<<endl; timh=diplasio(timh); cout<<"timh2 (TIMH1 x 2): "<<timh<<endl; timh=diplasio(timh); cout<<"timh3 (TIMH2 x 2): "<<timh<<endl; cout<<endl; return 0; int Diplasio(int timh) return 2*timh; Σύντομη εξήγηση του προγράμματος. Εδώ έχουμε ορίσει μία inline συνάρτηση (Diplasio) που την καλούμε μέσα στην main τρεις φορές. Ουσιαστικά ο compiler αντιγράφει τον κώδικα της συνάρτησης σε κάθε σημείο της main που καλείται η συνάρτηση. Με αυτό τον τρόπο δεν έχουμε τρεις μεταπηδήσεις από την main στην συνάρτηση και έτσι κερδίζουμε χρόνο κατά την εκτέλεση του προγράμματος. Χρησιμοποιούμε inline συναρτήσεις όταν η συνάρτηση έχει μία έως δύο εντολές και χρειάζεται να την καλέσουμε μέσα στην main πολλές φορές. 8
ΚΛΑΣΕΙΣ - ANTIKEIMENA Παραδείγματα ΔΗΛΩΣΗ ΜΙΑΣ ΑΠΛΗΣ ΚΛΑΣΗΣ Ορισμός μεθόδων μέσα στην κλάση class foithths //dhlosh klashs char onoma[30]; float vathmos; void readdata() //orismos ths readdata cout << "Dwse onoma:"; cin >> onoma; cout << "Dwse vathmo:"; cin >> vathmos; void printdata() //orismos ths printdata cout<<"to onoma toy foithth einai: "<<onoma<<endl; cout<<"o vathmos toy foithth einai: "<<vathmos<<endl; ; // telos klashs foithths f1, f2; // dhlosh antikeimenwn f1.readdata(); //klhsh synarthshs gia orismo dedomenwn f1.printdata(); //klhsh synarthshs gia emfanish dedomenwn f2.readdata(); f2.printdata(); Σύντομη εξήγηση του προγράμματος. Σε αυτό το παράδειγμα ο ορισμός των μεθόδων (Συναρτήσεων Μελών) γίνεται μέσα στην δήλωση της κλάσης. Τα δεδομένα μέλη είναι ιδιωτικά ορατά δηλ μπορούν να έχουν πρόσβαση σε αυτά οι μέθοδοι της ίδιας της κλάσης και οι μέθοδοι είναι δημόσια ορατές. Κατόπιν δημιουργούμε δύο αντικείμενα της κλάσης φοιτητής και καλούμε για το κάθε αντικείμενο τις συναρτήσεις για την εισαγωγή δεδομένων και την εκτύπωση δεδομένων. 9
Ορισμός μεθόδων έξω από την κλάση class foithths //dhlosh klashs char onoma[30]; float vathmos; void readdata(); void printdata(); ; // telos klashs //orismos ths readdata void foithths::readdata() cout << "Dwse onoma:"; cin >> onoma; cout << "Dwse vathmo:"; cin >> vathmos; //orismos ths printdata void foithths::printdata() cout << "To onoma toy foithth einai: " << onoma << endl; cout << "O vathmos toy foithth einai: " << vathmos << endl; foithths f1, f2; // dhlosh antikeimenwn f1.readdata(); //klhsh synarthshs gia orismo dedomenwn f1.printdata(); //klhsh synarthshs gia emfanish dedomenwn f2.readdata(); f2.printdata(); Σύντομη εξήγηση του προγράμματος. Σε αυτό το παράδειγμα ο ορισμός των μεθόδων (Συναρτήσεων Μελών) γίνεται έξω από την κλάση. Για να έχουν πρόσβαση τα αντικείμενα στις μεθόδους ο ορισμός των μεθόδων γίνεται με τον εξής τρόπο: τύποςσυνάρτησης όνομακλάσης::όνομασυνάρτησης(παράμετροι) Π.χ. void foithths::printdata() 10
ΑΠΟΔΟΣΗ ΤΙΜΩΝ ΜΕΣΑ ΑΠΟ ΤΙΣ ΠΑΡΑΜΕΤΡΟΥΣ # include <string.h> class foithths //dhlosh klashs char onoma[30]; float vathmos; void setdata(char onoma_new[], int vathmos_new) //orismos ths setdata strcpy(onoma, onoma_new); vathmos=vathmos_new; void printdata() //orismos ths printdata cout<<"to onoma toy foithth einai: "<<onoma<<endl; cout<<"o vathmos toy foithth einai: "<<vathmos<<endl; ; // telos klashs foithths f1; f1.setdata("marios TSOUKALAS", 6.5); f1.printdata(); Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα ορίζουμε μία μέθοδο setdata, ο οποία όταν κληθεί στην main, μεταβιβάζονται οι τιμές MARIOS TSOUKALAS και 6.5 στις αντίστοιχες onoma_new και vathmos_new. Έτσι όταν τρέξει το πρόγραμμα το αντικείμενο θα έχει ήδη τιμές. Χρησιμοποιούμε το αρχείο κεφαλίδας string.h το οποίο περιλαμβάνει την συνάρτηση strcpy για να μεταφέρουμε τις τιμές του πίνακα χαρακτήρων onoma_new στον πίνακα onoma. 11
ΧΕΙΡΙΣΜΟΣ ΚΛΑΣΗΣ Το παρακάτω πρόγραμμα δημιουργεί (μία κλάση) έναν σκύλο, ορίζει την ηλικία του, μας γαυγίζει και μας λέει την ηλικία του. class Dog // dhlosh ths klashs // dhmosia enothta int GetDogAge(); // voithitikh synarthsh void SetDogAge (int age); // voithitikh synarthsh void Bark(); // genikh synarthsh // idiotikh enothta int itsage; // metavlhth melous ; //telos klashs /* orismos dhmosias vohthitikhs synarthshs GetAge epistrefei thn timh toy meloys itsage */ int Dog::GetDogAge() return itsage; /* orismos dhmosias vohthitikhs synarthshs SetAge epistrefei thn timh toy meloys itsage */ void Dog::SetDogAge(int age) /* pernaei thn timh ths parametroy age sthn metavlhth itsage */ itsage = age; /* orismos thw methodoy Bark epistrefei void, den exei parametrous typonei Bark sthn othonh */ void Dog::Bark() cout << "Bark!!!\n"; /* dhmiourgia enos skyloy, orismos ths hlikias toy ton kanei na gaygizei kai na leei thn hlikia toy*/ int main() Dog Max; //orismos antikeimenoy Max.SetDogAge(2); //dhlosh timhs sto itsage Max.Bark(); cout << "o Max o skylos moy einai " ; cout << Max.GetDogAge() << " xronwn \n"; //anagnosh timhs Max.Bark(); return 0; //telos ths main 12
Σύντομη εξήγηση του προγράμματος. Στην αρχή του προγράμματος δηλώνουμε την κλάση Dog η οποία περιέχει τις δύο δημόσιες βοηθητικές μεθόδους (συναρτήσεις) GetDogAge(), SetDogAge(int age) και την μία δημόσια γενική Bark() καθώς και την ιδιωτική μεταβλητή μέλους itsage. Αμέσως μετά ορίζεται η συνάρτηση μέλος GetDogAge() η οποία επιστρέφει την τιμή της itsage. Εδώ βλέπουμε ότι η main() έχει πρόσβαση μόνο στην GetDogAge() που είναι δημόσια και όχι στην itsage που είναι ιδιωτική. Η GetDogAge() που είναι συνάρτηση μέλος της κλάσης Dog έχει πρόσβαση στην itsage και έτσι μπορεί να επιστρέψει την τιμή της στην main(). Στην συνέχεια ορίζεται η συνάρτηση μέλος SetDogAge() που έχει μία ακέραια παράμετρο και δίνει στο itsage την τιμή αυτής της παραμέτρου. Η συνάρτηση αυτή έχει πρόσβαση στην μεταβλητή μέλος ItsAge λόγω του ότι είναι μέλος της κλάσης Dog. Στο επόμενο βήμα ορίζουμε την γενική δημόσια συνάρτηση Bark() η οποία τυπώνει στην οθόνη την λέξη Bark (Γαβ). Αμέσως μετά αρχίζει η main() η οποία ορίζει ένα αντικείμενο Max της κλάσης Dog, δίνει την τιμή 2 στην μεταβλητή μέλος itsage μέσω της μεθόδου SetDogAge() η οποία ξεκινά με το όνομα του αντικειμένου, τον τελεστή μέλους (.) και το όνομα της μεθόδου. Ύστερα καλείται η συνάρτηση μέλος Bark() δύο φορές και ενδιαμέσως τυπώνεται ένα μήνυμα που χρησιμοποιεί την συνάρτηση μέλος GetDogAge() του αντικειμένου Max για να εμφανίσει στην οθόνη την τιμή της itsage που εισήχθη πριν. Το πιο πάνω πρόγραμμα με την χρήση constructor με όρισμα και destructor class Dog Dog(int initialage); ~Dog(); int GetDogAge(); void SetDogAge(int age); void Bark(); int itsage; ; //telos ths klashs //dhlosh constructor me orisma //dhlosh destructor Dog::Dog(int initialage) //orismos constructor toy Dog itsage=initialage; Dog::~Dog() //orismos tou destructor 13
int main() /* kathorismos ths hlikias xoris na klhthei h SetDogAge Orismos antikeimenoy me perasma timhs ston constructor tou Max */ Dog Max(2); Max.Bark(); cout << "o Max o skylos moy einai " ; cout << Max.GetDogAge() << " xronwn \n"; Max.Bark(); Max.SetDogAge(9); //klhsh ths SetDogAge gia allagh hlikias cout << "twra o Max o skylos moy egine " ; cout << Max.GetDogAge() << " xronwn \n"; Max.Bark(); Max.Bark(); return 0; //telos ths main Σύντομη εξήγηση του προγράμματος. Εδώ βλέπουμε την χρήση των constructor με όρισμα και destructor. Στην main(), η ηλικία καθορίστηκε από την αρχή (τιμή 2 στην μεταβλητή μέλος itsage) και δεν χρειάστηκε να κληθεί η SetDogAge(). Η SetDogAge() καλείται μετέπειτα για να αλλάξουμε την ηλικία σε 9. Επισημαίνουμε ότι όταν ορίζουμε constructor πρέπει υποχρεωτικά να ορίσουμε και destructor. 14
ΜΕΤΑΦΟΡΑ ΔΕΔΟΜΕΝΩΝ ΚΛΑΣΗΣ ΣΕ ΣΥΝΑΡΤΗΣΗ #include <process.h> #include <math.h> class paradeigma int a,b,s,c; void getdata(int k, int l) //metafora timon sthn klash a=k; b=l; int calcdatasqr() //athroisma ton tetragonon s=pow(a,2)+pow(b,2); return s; int calcdatacube() //athroisma ton kyvon c=pow(a,3)+pow(b,3); return c; void printsqrtdata() //ektyposh athroismatos twn tetragonon cout<<" 1os arithmos: "<<a<<endl; cout<<" 2os arithmos: "<<b<<endl; cout<<"athroisma Tetragonon: "<<s<<endl; void printcubedata() //ektyposh athroismatos twn kyvon cout<<" 1os arithmos: "<<a<<endl; cout<<" 2os arithmos: "<<b<<endl; cout<<"athroisma Kyvon: "<<c<<endl; ; //telos klashs paradeigma par1,par2; //antikeimena ths klashs int za,zb,apotsqrt,apotcube; //topikes metavlhtes int float rizasqrt, rizacbrt; //topikes metavlhtes float while(1) //synexomenh epanalhpsi (1>0) cout<<"dose 2 arithmous"<<endl; cout<<"h dose 0 0 gia exodo"<<endl; cin>>za; cin>>zb; if((za==0)&&(zb==0)) //exodus an kai oi 2 arithmoi einai 0 cout<<"exodos apo to programma"<<endl; exit(0); 15
cout<<"**************************************"<<endl; par1.getdata(za,zb); //apostolh timon sthn klash apotsqrt=par1.calcdatasqr(); par1.printsqrtdata(); //ektyposh dedomenon cout<<"to athroisma ton tetragonon einai: "<<apotsqrt<<endl; rizasqrt=sqrt(apotsqrt); //ypologismos tetragonikhs rizas cout<<"h tetragonikh riza toy athroismatos einai: "<<rizasqrt<<endl; cout<<"**************************************"<<endl; par2.getdata(za,zb); apotcube=par2.calcdatacube(); par2.printcubedata(); cout<<"to athroisma ton kyvon einai: "<<apotcube<<endl; rizacbrt=pow(apotcube, (float)1/3); cout<<"h kyvikh riza toy athroismatos einai: "<<rizacbrt<<endl; //telos main Σύντομη εξήγηση του προγράμματος. Σε αυτό το πρόγραμμα βάζουμε 2 αριθμούς και υπολογίζουμε το άθροισμα των τετραγώνων τους και την τετραγωνική ρίζα του αθροίσματος, καθώς και το άθροισμα των κύβων τους και την κυβική ρίζα του αθροίσματος. Καλούμε τις συναρτήσεις της κλάσης paradeigma στέλνοντας τις τιμές των μεταβλητών που βρίσκονται μέσα στην main(). Μέσα στην main() έχουμε ένα βρόχο while με συνθήκη (1) ή αλλιώς (1>0) που ισοδυναμεί με διαρκή επανάληψη των εντολών του βρόχου. Ο βρόχος τερματίζεται όταν και οι δύο αριθμοί που θα εισαχθούν θα είναι ίσοι με 0 (μέσα σε μία δομή επιλογής if). Για τον υπολογισμό της δύναμης χρησιμοποιούμε την συνάρτηση pow() της βιβλιοθήκης math.h. Για τον υπολογισμό της τετραγωνικής ρίζας χρησιμοποιούμε την συνάρτηση sqrt(). Για τον υπολογισμό της κυβικής ρίζας χρησιμοποιούμε την συνάρτηση pow() με ορίσματα τον αριθμό και το 1/3 γιατί από τα μαθηματικά γνωρίζουμε ότι όταν θέλουμε να βρούμε την ρίζα ενός αριθμού αρκεί να τον υψώσουμε σε 1/δύναμη. Επίσης επειδή το 1/3 θεωρείται από την γλώσσα πηλίκο ακεραίων και όταν εφαρμοστεί στην pow() θα δίνει αποτέλεσμα πάντα 1 (γιατί 1/3=0 και αριθμός^0=1) κάνουμε casting σε τύπο float στο πηλίκο. 16
ΚΛΑΣΗ ΜΕ ΥΠΕΡΦΟΡΤΩΣΗ CONSTRUCTOR Στο παρακάτω πρόγραμμα δηλώνουμε μία κλάση για τον υπολογισμό του εμβαδού ενός τριγώνου. Κάνουμε χρήση συνάρτησης εγκατάστασης (constructor- destructor) με υπερφόρτωση. class Trigono //dhlodh klashs int vash; int ypsos; Trigono() //constructor xoris orisma vash = 5; ypsos = 3; Trigono(int v,int y) //constructor me orisma vash = v; ypsos = y; ~Trigono() //destructor int emvado() //synarthsh ypologismoy toy emvadou return (vash*ypsos)/2; ; //telos klashs int main () Trigono TrigA (8,3); //antikeimen ths klashs me times Trigono TrigB; //antikeimen ths klashs xoris times /* klhsh synarthshs ypologismoy toy embadoy me taytoxronh ektyposh sthn othonh toy apotelesmatos */ cout << "Emvado Trigonou A: " << TrigA.emvado() << endl; cout << "Emvado Trigonou B: " << TrigB.emvado() << endl; return 0; //telos main Σύντομη εξήγηση του προγράμματος. Σε αυτό το πρόγραμμα φτιάχνουμε μια κλάση Trigono, την οποία θα χρησιμοποιούμε για τον υπολογισμό του εμβαδού ενός τριγώνου. Τα αντικείμενα της κλάσης μπορούν να έχουν δικές τους τιμές (βάση, ύψος) ή να χρησιμοποιούν προεπιλεγμένες. Αυτό γίνεται με την χρήση συναρτήσεων εγκατάστασης (constructor-destructor) με υπερφόρτωση δηλαδή constructor με όρισμα και χωρίς όρισμα. 17
ΔΗΛΩΣΗ ΚΛΑΣΗΣ class proion //dhlosh klashs int code; char name[20]; float init_price; float sales_price; float rate; proion() init_price=0; sales_price=0; ~proion() //synarthsh eisagoghs stoixeiwn void pr_set_data() cout<<"dose KWDIKO: "<<; cin>>code; cout<<"dose ONOMA EIDOUS: "<<; cin>>name; cout<<"dose TIMH AGORAS: "<<; cin>>init_price; cout<<"dose POSOSTO KERDOUS (%): "<<; cin>>rate; cout<<"-------------------------------"<<endl; // ektyposh stoixeion me klhsh synarthsewn ypologismwn void pr_print_data() float a; cout<<"kvdikow EIDOUS: "<<code<<endl; cout<<"onoma EIDOUS: "<<name<<endl; cout<<"timh AGORAS: "<<init_price<<" EURO"<<endl; a=calc_profit_price(init_price, rate); //ypologismos kerdoys sales_price=calc_final_price(a); //ypologismos FPA cout<<"timh PWLHSHS XORIS FPA: "<<a<<" EURO"<<endl; cout<<"timh PWLHSHS ME FPA: "<<sales_price<<" EURO"<<endl; cout<<"-------------------------------"<<endl; //synarthsh ypologismou ths timhs polhshs float calc_profit_price(float x, float y) 18
return x+=x*y/100; //synarthsh ypologismoy toy FPA 23% float calc_final_price(float z) return z+=z*23/100; // epistrofh timhs agoras float get_init_price() return init_price; // epistrofh telikhs timhs float get_sales_price() return sales_price; ; //telos klashs proion pr1,pr2; pr1.pr_set_data(); pr2.pr_set_data(); pr1.pr_print_data(); pr2.pr_print_data(); // telos main Στο παραπάνω πρόγραμμα δηλώνουμε μια κλάση proion η οποία έχει ως δεδομένα μέλη τα εξής: κωδικός, όνομα, τιμή αγοράς, τιμή πώλησης με ΦΠΑ (23%), ποσοστό κέρδους. Έχει επίσης και τις μεθόδους: α) εισαγωγή στοιχείων στα αντικείμενα, β) εκτύπωση των στοιχείων των αντικειμένων, γ) υπολογισμός του κέρδους πάνω στην τιμή αγοράς, δ) υπολογισμός τελικής τιμής με ΦΠΑ, ε) επιστροφή της αρχικής τιμής (τιμή αγοράς) και ζ) επιστροφή της τελικής τιμής (με ΦΠΑ). Μέσα στην μέθοδο pr_print_data καλούμε την μέθοδο calc_profit_price που υπολογίζει την τελική τιμή του είδους (με ορίσματα την τιμή αγοράς του αντικειμένου και το ποσό του κέρδους) και την calc_final_price με την οποία υπολογίζουμε την τελική τιμή του είδους με ΦΠΑ 23% με όρισμα την τιμή επιστροφής της calc_profit_price Έχουμε δηλώσει constructor που αρχικοποιεί τα δεδομένα: τιμή αγοράς και τελική τιμή στην τιμή 0. Τα αντικείμενα που κατασκευάζουμε στην main() καλούν τις μεθόδους της κλάσης για εισαγωγή και εκτύπωση των δεδομένων. 19
ΚΛΑΣΕΙΣ ANTIKEIMENA 2 Παραδείγματα CONSTRUCTOR ΜΕ ΥΠΕΡΦΟΡΤΩΣΗ class logariasmos float ypoloipo; logariasmos() // constructor xoris orisma ypoloipo=0; logariasmos(float arxiko_ypoloipo) // constructor me orisma ypoloipo=arxiko_ypoloipo; ~logariasmos() //dhlosh destructor void analhpsh(float poso) if (poso<=ypoloipo) ypoloipo=ypoloipo-poso; else cout<<"prosoxh!!!!! To poso ths analhpsis "<<endl; cout<<" Einai megalytero apo to ypoloipo"<<endl; void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; ; logariasmos log1,log2(20),log3(200); cout <<"To ypoloipo toy log1:"<<log1.pareypoloipo()<<endl; cout <<"To ypoloipo toy log2:"<<log2.pareypoloipo()<<endl; cout <<"To ypoloipo toy log3:"<<log3.pareypoloipo()<<endl; cout<<"log1 katathesi 100E"<<endl; log1.katathesi(100); cout <<"To ypoloipo toy log1:"<<log1.pareypoloipo()<<endl; cout <<"To ypoloipo toy log2:"<<log2.pareypoloipo()<<endl; cout <<"To ypoloipo toy log3:"<<log3.pareypoloipo()<<endl; 20
Σύντομη εξήγηση του προγράμματος. Σε αυτό το παράδειγμα δηλώνουμε 2 constructors. Ο ένας με όρισμα και ο άλλος χωρίς. Κατόπιν δημιουργούμε τρία αντικείμενα της κλάσης με αρχικοποίηση του υπολοίπου στο πρώτο από τον constructor δίχως όρισμα (δηλ στην τιμή 0) και στα άλλα δύο με τιμή αρχικοποίησης κατά την δημιουργία. Μετά κάνουμε κατάθεση στο ένα αντικείμενο και βλέπουμε ότι το υπόλοιπο άλλαξε μόνο για το αντικείμενο το οποίο έκανε την κατάθεση. ΧΡΗΣΗ ΑΝΤΙΚΕΙΜΕΝΟΥ ΣΑΝ ΟΡΙΣΜΑ ΣΥΝΑΡΤΗΣΗΣ class logariasmos float ypoloipo; logariasmos() ypoloipo=0; logariasmos(float arxiko_ypoloipo) ypoloipo=arxiko_ypoloipo; ~logariasmos() void analhpsh(float poso) if (poso<=ypoloipo) ypoloipo=ypoloipo-poso; else cout<<"prosoxh!!!!! To poso ths analhpsis "<<endl; cout<<" Einai megalytero apo to ypoloipo"<<endl; void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; // orismos synarthshs prostheshs ypoloipon. void athrypoloipo(logariasmos a, logariasmos b) ypoloipo=a.ypoloipo+b.ypoloipo; ; 21
logariasmos log1(200),log2(500),log3; cout <<"To ypoloipo toy log1:"<<log1.pareypoloipo()<<endl; cout <<"To ypoloipo toy log2:"<<log2.pareypoloipo()<<endl; cout <<"To ypoloipo toy log3:"<<log3.pareypoloipo()<<endl; // klhsh synarthshs me orismata ta dyo antikeimena // H synarthsh xrhsimopoiei san orismata ta dyo antikeimena log3.athrypoloipo(log1,log2); cout <<"synolo logariasmon:"<<log3.pareypoloipo()<<endl; Σύντομη εξήγηση του προγράμματος. Σε αυτό το παράδειγμα δημιουργούμε τρία αντικείμενα της κλάσης με αρχικοποίηση του υπολοίπου στο τελευταίο από τον constructor δίχως όρισμα (δηλ στην τιμή 0) και στα άλλα δύο με τιμή αρχικοποίησης κατά την δημιουργία. Φτιάχνουμε μία συνάρτηση η οποία προσθέτει τα υπόλοιπα των δύο πρώτων αντικειμένων. Κάνουμε κλήση αυτής της συνάρτησης όπου μεταβιβάζονται τα αντικείμενα log1 και log2 στις παραμέτρους της συνάρτησης a και b αντίστοιχα. Μέσα στο σώμα της συνάρτησης βλέπουμε την πρόσβαση αυτής στο δεδομένο του κάθε αντικειμένου (a.ypoloipo b.ypoloipo). Τα δεδομένα αυτά αν και είναι ιδιωτικά μπορούν να προσπελαστούν από την συνάρτηση γιατί αυτή είναι μέλος της κλάσης. Βλέπουμε επίσης ότι πριν την κλήση της συνάρτησης αυτής το υπόλοιπο του log3 ήταν 0 και μετά την κλήση της συνάρτησης έγινε 700. ΕΠΙΣΤΡΟΦΗ ΑΝΤΙΚΕΙΜΕΝΩΝ ΑΠΟ ΣΥΝΑΡΤΗΣΕΙΣ class logariasmos float ypoloipo; logariasmos() ypoloipo=0; logariasmos(float arxiko_ypoloipo) ypoloipo=arxiko_ypoloipo; ~logariasmos() void analhpsh(float poso) if (poso<=ypoloipo) ypoloipo=ypoloipo-poso; else 22
cout<<"prosoxh!!!! To poso ths analhpsis "<<endl; cout<<" Einai megalytero apo to ypoloipo"<<endl; void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; /* dhlosh antikeimenoy apotelesma kai Epistrofh toy apo thn synarthsh */ logariasmos athrypoloipo(logariasmos log) logariasmos apotelesma; /* prosthesi toy ypoloipo toy log1 me toy log2 kai ekxwrhsh sto ypoloipo toy apotelesma */ apotelesma.ypoloipo=ypoloipo+log.ypoloipo; ; return apotelesma; logariasmos log1(200),log2(500),log3; cout <<"To ypoloipo toy log1:"<<log1.pareypoloipo()<<endl; cout <<"To ypoloipo toy log2:"<<log2.pareypoloipo()<<endl; cout <<"To ypoloipo toy log3:"<<log3.pareypoloipo()<<endl; log3=log1.athrypoloipo(log2); //klhsh synarthshs cout <<"synolo logariasmon:"<<log3.pareypoloipo()<<endl; Σύντομη εξήγηση του προγράμματος. Αυτό το πρόγραμμα κάνει ότι ακριβώς και το προηγούμενο με διαφορετικό τρόπο. Εδώ στην συνάρτηση athrypoloipo μεταβιβάζουμε μόνο το ένα αντικείμενο στην παράμετρο log (το log2 στο log). Η τιμή του δεδομένου ypoloipo της παραμέτρου log προστίθεται στην τιμή του δεδομένου του αντικειμένου που καλεί την συνάρτηση δηλ του log1. Μέσα στην συνάρτηση ορίζουμε ένα αντικείμενο apotelesma στο οποίο θα εκχωρηθεί το αποτέλεσμα της πρόσθεσης των δύο υπολοίπων. Κατόπιν με την εντολή return το αντικείμενο apotelesma επιστρέφεται μέσα στην καλούσα συνάρτηση main και αποδίδεται στο αντικείμενο log3. Για να μπορέσει να επιστρέψει το αντικείμενο η συνάρτηση θα πρέπει να έχει τύπο επιστροφής την ίδια την κλάση. 23
ΣΤΑΤΙΚΑ ΔΕΔΟΜΕΝΑ ΚΛΑΣΗΣ class logariasmos static count=0; //dhlosh statikoy dedomenoy metrhrth float ypoloipo; logariasmos() count++; //xrhsh toy metrhrh ypoloipo=0; logariasmos(float arxiko_ypoloipo) count++; // xrhsh toy metrhrh ypoloipo=arxiko_ypoloipo; ~logariasmos() int getcount() //epistrefei thn timh toy metrhth return count; void analhpsh(float poso) if (poso<=ypoloipo) ypoloipo=ypoloipo-poso; else cout<<"prosoxh!!!!! To poso ths analhpsis "<<endl; cout<<" Einai megalytero apo to ypoloipo"<<endl; void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; logariasmos athrypoloipo(logariasmos log) logariasmos apotelesma; apotelesma.ypoloipo=ypoloipo+log.ypoloipo; return apotelesma; ; logariasmos log1(200),log2(500),log3; cout <<"To ypoloipo toy log1:"<<log1.pareypoloipo()<<endl; cout <<"To ypoloipo toy log2:"<<log2.pareypoloipo()<<endl; 24
cout <<"To ypoloipo toy log3:"<<log3.pareypoloipo()<<endl; log3=log1.athrypoloipo(log2); cout <<"synolo logariasmon:"<<log3.pareypoloipo()<<endl; cout<<"arithmos Pelaton"<<log1.getCount()<<endl; //count=3 cout<<"arithmos Pelaton"<<log2.getCount()<<endl; //count=3 cout<<"arithmos Pelaton"<<log3.getCount()<<endl; //count=3 Σύντομη εξήγηση του προγράμματος. Εδώ ορίζουμε ένα στατικό δεδομένο count στην κλάση logariasmos το οποίο δίνει την δυνατότητα σε κάθε αντικείμενο της κλάσης να γνωρίζει πόσα αντικείμενα υπάρχουν (ή αλλιώς τα αντικείμενα μοιράζονται την ίδια πληροφορία). Οι συναρτήσεις εγκατάστασης constructors, αυξάνουν κατά ένα κάθε φορά που δημιουργείται ένα αντικείμενο το στατικό δεδομένο μέλος count. Η συνάρτηση getcount που προσθέσαμε μέσα στην κλάση επιστέφει την τιμή που έχει το count την δεδομένη χρονική στιγμή. Έτσι και οι τρεις κλήσης της συνάρτησης που γίνονται μέσα στην main επιστρέφουν την τιμή 3, δηλ ουσιαστικά μας δείχνει τον αριθμό των αντικειμένων. Εάν δηλώναμε σαν κανονική μεταβλητή το count τότε κάθε constructor θα αύξανε κατά 1 το δικό του αντίγραφο και θα παίρναμε αυτή την τιμή για κάθε ξεχωριστό αντικείμενο. ΔΗΛΩΣΕΙΣ ΚΛΑΣΕΩΝ ΣΕ ΑΡΧΕΙΑ ΕΠΙΚΕΦΑΛΙΔΑΣ - INLINE & CONST ΜΕΘΟΔΟΙ Παράδειγμα 1 Dog.hpp //Dog.hpp class Dog Dog(int initialage) itsage=initialage; ~Dog() int GetDogAge() const return itsage; //const inline void SetDogAge(int age) itsage=age; //inline void Bark() const cout<< Bark!!!\n ; //const inline int itsage; ; Σύντομη εξήγηση του προγράμματος. Το πρόγραμμα δήλωσης της κλάσης Dog είναι χωρισμένο σε αρχείο κεφαλίδας Dog.hpp και αρχείο κυρίως κώδικα Dog.cpp. 25
Δηλώνουμε τρεις μεθόδους inline εκ των οποίων οι δύο είναι const δηλαδή δεν θα αλλάξουν την τιμή του δεδομένου-μέλους itsage Dog.cpp //Dog.cpp #include Dog.hpp //συμπερίληψη του αρχείου κεφαλίδας int main() Dog Max(2); Max.Bark(); cout << "o Max o skylos moy einai " ; cout << Max.GetDogAge() << " xronwn \n"; Max.Bark(); Max.SetDogAge(9); cout << "twra o Max o skylos moy egine " ; cout << Max.GetDogAge() << " xronwn \n"; Max.Bark(); Max.Bark(); return 0; ΔΗΛΩΣΕΙΣ ΚΛΑΣΕΩΝ ΣΕ ΑΡΧΕΙΑ ΕΠΙΚΕΦΑΛΙΔΑΣ Παράδειγμα 2 Parallhlogramo.hpp //Parallhlogramo.hpp class Parallhlogramo float platos, ypsos; Parallhlogramo (float x, float y) platos = x; ypsos = y; ~Parallhlogramo () float emvado() return (platos*ypsos); ; //telos klashs Trigono.hpp //Trigono.hpp class Trigono float vash; float ypsos; 26
Trigono(float v, float y) vash = v; ypsos = y; ~Trigono() float emvado() return (vash*ypsos)/2; ; //telos klashs Kyklos.hpp //Kyklos.hpp class Kyklos float aktina; Kyklos float a) aktina = a; ~ Kyklos() float emvado() return (aktina*aktina*3.14); ; //telos klashs Kylindros.hpp //Kylindros.hpp class kylindros float aktina,ypsos; kylindros(float a, float h) aktina=a; ypsos=h; float ogkos() return (aktina*aktina*ypsos*3.14); ; //telos klashs 27
//ypologismoi.cpp #include Parallhlogramo.hpp #include Trigono.hpp #include Kyklos.hpp #include Kylindros.hpp Parallhlogramo P_a(12,30); Trigono T_a(3.4,5.0); Kyklos K_a(5); Kylindros Kyl_a(2.3,8.0); Cout<< Emvado Parallhlogramoy <<P_a.emvado()<<endl; Cout<< Emvado Trigwnou <<T_a.emvado()<<endl; Cout<< Epifaneia Kykloy <<K_a.emvado()<<endl; Cout<< Ogkos Kylindroy <<Kyl_a.ogkos()<<endl; ; //telos main Σύντομη εξήγηση του προγράμματος. Εδω έχουμε δηλώσει 4 κλάσεις σε αντίστοιχα αρχεία επικεφαλίδας. Τις κλάσεις τις χρησιμοποιούμε μέσαστο κυρίως πρόγραμμα ypologismoi.cpp συμπεριλμβάνοντάς τες με διαδοχικά includes. ΔΗΜΙΟΥΡΓΙΑ ΚΑΙ ΧΡΗΣΗ ΑΝΤΙΚΕΙΜΕΝΟΥ ΜΙΑΣ ΚΛΑΣΗΣ ΣΕ ΜΙΑ ΑΛΛΗ class kyklos float aktina; kyklos(float r) : aktina(r) float emvado() return aktina*aktina*3.14; ; class kylindros kyklos vash; float ypsos; kylindros(float v, float h) : vash (v), ypsos(h) float ogkos() return vash.emvado() * ypsos; ; int main () 28
kylindros kyl1 (10,20); cout << "ogkos kyl1 : " << kyl1.ogkos() << '\n'; return 0; Σύντομη εξήγηση του προγράμματος. Αυτό το πρόγραμμα έχει 2 κλάσεις, μία για τον υπολογισμό της επιφάνειας του κύκλου με την βοήθεια του τύπου Ε κ =π*r 2 και μία του για τον υπολογισμό του όγκου του κυλίνδρου με την βοήθεια του τύπου V κυλ =Εκ*h. όπου π=3.14, r=ακτίνα κύκλου, h=ύψος κυλίνδρου. Στο πρόγραμμα αυτό μπορούμε ανεξάρτητα να υπολογίζουμε την επιφάνεια κύκλου φτιάχνοντας ένα αντικείμενο της κλάσης kyklos το οποίο καλεί την συνάρτηση emvado() της κλασης kyklos, αλλά και τον όγκο κυλίνδρου φτιάχνοντας αντίστοιχα ένα αντικείμενο της κλάσης kylindros, με την μόνη διαφορά ότι μέσα στην κλάση κύλινδρος φτιάχνουμε ένα αντικείμενο της κλάσης κύκλος το οποίο χρησιμοποιείται από την συνάρτηση ogkos() της κλάσης kylindros για να καλέσει την συνάρτηση emvado() της κλασης kyklos η οποία επιστρέφει την επιφάνεια του κύκλου που με την σειρά της θα πολλαπλασιαστεί με το ύψος του κυλίνδρου για να επιστρέψει τον όγκο στην main(). Επίσης βλέπουμε την διαφορετική λειτουργία των constructors με αντιστοίχιση ορισμάτων με δεδομένα, όπου στην κλάση kyklos ο constructor kyklos αρχικοποιεί την ακτίνα aktina(r), ενώ στην κλάση kylindros το αντικείμενο στέλνει δύο τιμές (10,20) από τις οποίες η πρώτη είναι η ακτίνα που αποδίδεται από τον constructor kylindros ως τιμή στο αντικείμενο vash (v) άρα και κατ επέκταση στο δεδομένομέλος aktina της κλκάσης kyklos και η δεύτερη είναι το ύψος η οποία αποδίδεται κανονικά στο δεδομένο-μέλος ypsos (h) της κλάσης kylindros. ΠΑΡΑΔΕΙΓΜΑ ΧΡΗΣΗΣ ΚΛΑΣΗΣ class iatroi int am; char name[10]; char surname[20]; char speciality[20]; int hours; float payrate; float salary; iatroi(); iatroi(float p):payrate(p); ~iatroi(); void readdata(); float salcalc(int hrs, float prt); float salarybonus(float a); 29
float salarybonusper(float a); float returnsalary(); float returnpayrate(); float returnhours(); int returnam(); void showspeciality(); void showdata(); ; iatroi::iatroi() payrate=25; iatroi::iatroi(float p):payrate(p) iatroi::~ iatroi() void iatroi::readdata() cout<<"a.m.:"; cin>>am; cout<<"name:"; cin>>name; cout<<"surname:"; cin>>surname; cout<<"ores:"; cin>>hours; salary=salcalc(hours, payrate); float iatroi::salcalc(int hrs, float prt) float sal; sal=hrs*prt; return sal; float iatroi::salarybonus(float a) return salary+=a; float iatroi::salarybonusper(float a) return salary+=salary*a/100; float iatroi::returnsalary() return salary; float iatroi::returnpayrate() return payrate; float iatroi::returnhours() return hours; int iatroi::returnam() 30
return am; void iatroi::showspeciality() cout<<speciality<<endl; void iatroi::showdata() cout<<"a.m.: "<<am<<endl; cout<<"name: "<<name<<endl; cout<<"surname: "<<surname<<endl; cout<<"eidikothta: "<<speciality<<endl; cout<<"ores Ergasias: "<<hours<<endl; cout<<"oromisthio: "<<payrate<<endl; cout<<"misthos: "<<salary<<" Euro"<<endl; iatroi i1(20), i2, i3(110); i1.readdata (); i2.readdata (); i3.readdata (); cout<<endl; i1.showdata (); cout<<endl; i2.showdata (); cout<<endl; i3.showdata (); cout<<endl; Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα ορίζεται μια κλάση iatroi. Τα δεδομένα μέλη είναι: ο αριθμός μητρώου, το όνομα, το επώνυμο, η ειδικότητα, οι ώρες εργασίας, το ωρομίσθιο και το ημερομίσθιο. Χρησιμοποιείται constructor με υπερφόρτωση. Δηλαδή το ωρομίσθιο χρησιμοποιείται σαν δεδομένο αρχικοποίησης στον constructor χωρίς όρισμα με τιμή 25. Επίσης χρησιμοποιείται και constructor με αντιστοίχιση ορισμάτων με τα δεδομένα. Η κλάση περιέχει εκτός από τους constructors τις εξής συναρτήσεις: 1. Συνάρτηση για την εισαγωγή των δεδομένων των ιατρών readdata() (με κλήση της συνάρτησης υπολογισμού του ημερομισθίου), 2. Συνάρτηση για τον υπολογισμό του ημερομισθίου salcalc(), 3. Συνάρτηση για τον υπολογισμό χρηματικής αύξησης μισθού salarybonus (), 31
4. Συνάρτηση για τον υπολογισμό ποσοστιαίας αύξησης μισθού salarybonusper (), 5. Συνάρτηση για την εμφάνιση των δεδομένων showdata(), 6. Συνάρτηση για την επιστροφή των ωρών εργασιας returnhours(), 7. Συνάρτηση για την επιστροφή του ημερομισθίου returnpayrate(), 8. Συνάρτηση για την επιστροφή του μισθού returnsalary(), 9. Συνάρτηση για την επιστροφή του αριθμού μητρώου returnam() και 10. Συνάρτηση για την εμφάνιση της ειδικότητας showspeciality(). Για καλύτερο έλεγχο της κλάσης οι δηλώσεις των συθναρτ πησεων περιέχονται στην κλάση ενώ οι ορισμοί τους βρίσκονται έξω από αυτήν. 32
ΜΟΝΟΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ ΠΙΝΑΚΕΣ Διάβασμα μονοδιάστατου πίνακα. for (int i=0; i<n; i++) cin>>arr[i]; Εμφάνιση μονοδιάστατου πίνακα. for (int i=0; i<n; i++) cout<<arr[i]; Άθροισμα στοιχείων μονοδιάστατου πίνακα. int sum=0; for (int i=0; i<n; i++) sum=sum+arr[i]); ΔΙΣΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ Διάβασμα δισδιάστατου πίνακα. for (int i=0; i<m; i++) for (int j=0; j<n; j++) cin>>arr[i][j]; Εμφάνιση δισδιάστατου πίνακα. for (int i=0; i<m; i++) for (int j=0; j<n; j++) cout<<arr[i][j]; Άθροισμα στοιχείων δισδιάστατου πίνακα. int sum=0; for (int i=0; i<μ; i++) for (int j=0; j<n; j++) sum=sum+arr[i][j]); Άθροισμα στοιχείων δισδιάστατου πίνακα ανά γραμμή. for (int i=0; i<μ; i++) row[i]=0; for (int j=0; j<n; j++) row[i]=row[i]+arr[i][j]; Άθροισμα στοιχείων δισδιάστατου πίνακα ανά στήλη. for (int j=0; j<n; j++) col[j]=0; for (int i=0; i<μ; i++) col[j]=col[j]+arr[i][j]; 33
Παραδείγματα ΜΟΝΟΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ Ακολουθεί ένα πρόγραμμα που διαβάζει είκοσι ακέραιους από το πληκτρολόγιο και εμφανίζει το πλήθος των άρτιων και το πλήθος των περιττών. #define N 20 int arr[n]; int i, artios=0, perittos=0 ; for (i=0; i<n; i++) cout<<"dose "<<i+1<<"o arithmo:"; cin>>arr[i]; for (i=0; i<n; i++) if (arr[i]%2==0) artios=artios+1; else perittos=perittos+1; cout<<"oi Artioi einai: "<<artios<<endl; cout<<"oi Perittoi einai: "<< perittos << endl; ΔΙΣΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ 1. Το πιο κάτω πρόγραμμα υπολογίζει το άθροισμα των στοιχείων ενός δισδιάστατου πίνακα ανά γραμμή. #define M 3 #define N 3 int i,j; int myarray[m][n]; //vasikos pinakas int row[m]; //vohthitikos pinakas /* vroxos gia thn eisafvgh twn timwn tou pinaka apo ton xrhsth */ for(i=0;i<m;i++) for(j=0;j<n;j++) cout<<"timh gia to myarray["<<i<<"]["<<j<<"]: "; cin>>myarray[i][j]; // vroxos gia ton ypologismo toy athroismatos for(i=0;i<m;i++) row[i]=0; for(j=0;j<n;j++) row[i]=row[i]+myarray[i][j]; cout<<"to athroisma ths grammhs "<<i<<" einai: "<<row[i]<<endl; 34
2. Το πιο κάτω πρόγραμμα υπολογίζει το άθροισμα των στοιχείων ενός δισδιάστατου πίνακα ανά στήλη. #define M 3 #define N 3 int i,j; int myarray[m][n]; //vasikos pinakas int col[n]; //vohthitikos pinakas /* vroxos gia thn eisafvgh twn timwn tou pinaka apo ton xrhsth */ for(i=0;i<m;i++) for(j=0;j<n;j++) cout<<"timh gia to myarray["<<i<<"]["<<j<<"]: "; cin>>myarray[i][j]; // vroxos gia ton ypologismo toy athroismatos for(j=0;j<n;j++) col[j]=0; for(i=0;i<m;i++) col[j]=col[j]+myarray[i][j]; cout<<"to athroisma ths sthlhs "<<j<<" einai: "<<col[j]<<endl; 3. Το πρόγραμμα που ακολουθεί χρησιμοποιεί τρεις πίνακες ως εξής: Ένα μονοδιάστατο πίνακα 5 θέσεων όπου βρίσκονται καταχωρημένα τα ονόματα 5 πόλεων, Ένα μονοδιάστατο πίνακα 12 θέσεων όπου βρίσκονται καταχωρημένα τα ονόματα των 12 μηνών, Ένα δισδιάστατο πίνακα 5x12 όπου βρίσκονται καταχωρημένοι οι μέσοι όροι θερμοκρασίας που καταγράφηκαν σε κάθε πόλη για κάθε μήνα. Το πρόγραμμα θα εμφανίζει τις θερμοκρασίες όλων των πόλεων για κάθε μήνα, και θα βρίσκει και θα εμφανίζει την ελάχιστη και τη μέγιστη θερμοκρασία ανά πόλη και μήνα. #define M 5 #define N 12 main() char cities[m][80]="kavala", "DRAMA", "THESSALONIKI", "SERRES", "LARISSA"; char months[n][80] = "IANOYARIO","FEBROUARIO","MARTIO","APRILIO", "MAIO","IOYNIO","IOYLIO","AVGOUSTO","SEPTEMBRIO", "OKTOBRIO", "MOEMBRIO","DEKEMBRIO"; 35
float temp[m][n] = 15.6,13.8,16.9,18.2,19.3,26.7,29.5,33.4,22.5,18.4,17.5,14.2, 13.5,12.9,15.8,17.3,18.2,24.9,28.9,30.1,21.7,17.1,15.8,13.8, 15.9,14.2,17.3,19.4,21.5,17.9,30.6,34.2,24.1,19.6,18.2,14.7, 16.3,15.9,17.8,19.8,22.2,18.3,30.8,35.1,25.5,20.5,18.8,15.3, 18.3,17.1,19.6,22.4,25.3,30.2,32.4,36.3,31.5,22.7,21.5,19.4 ; float mintemp, maxtemp; int i,j, row, col; for (i=0; i<m; i++) //emfanish twn 8ermokrasiwn ana polh cout<<cities[i]; for (j=0; j<n; j++) cout<<temp[i][j]; cout<<endl; mintemp=temp[0][0]; //evresh ths mikroterhs 8ermokrasias row=0; col=0; for (i=0; i<m; i++) for (j=0; j<n; j++) if (temp[i][j]<mintemp) mintemp=temp[i][j]; row=i; //h polh me thn mikroterh 8ermokrasia. col=j; //o mhnas me thn mikroterh 8ermokrasia. cout<<endl<<"mikroterh Thermokrasia: "<<mintemp<<endl; cout<<"stin: "<<cities[row]<<endl; cout<<"to Mhna: "<<months[col]<<endl; maxtemp=temp[0][0]; row = 0; col = 0; for (i=0; i<m; i++) //evresh ths megalyterhs 8ermokrasias for (j=0; j<n; j++) if (temp[i][j]>maxtemp) maxtemp=temp[i][j]; row=i; //h polh me thn megalyterh 8ermokrasia. col=j; //o mhnas me thn megalyterh 8ermokrasia. cout<<endl<<"megalyterh Thermokrasia: "<<maxtemp<<endl; cout<<"stin: "<<cities[row]<<endl; cout<<"to Mhna: "<<months[col]<<endl; return 0; 36
ΠΙΝΑΚΕΣ & ΚΛΑΣΕΙΣ Οι πίνακες μπορούν να χρησιμοποιηθούν ως δεδομένα κλάσεων αλλά και ως μέρη των μεθόδων κλάσεων. Μπορούν να είναι πίνακες απλοί ή ακόμα και πίνακες αντικειμένων. Πίνακας ως δεδομένο μιας κλάσης. char Polh[30]; float Temp[N]; Πίνακας ως μέλος μεθόδου. void readdata() cout<<"dose A.M.:"; cin >> armht; cout <<"Dose Vathmous: "; for (int i=0; i<n; i++) cin>>vathmos[i]; Πίνακας αντικειμένων μιας κλάσης. Void main() Temperature Tem[N]; for (i=0; i<n; i++) Tem[i].setTemp(); Αρχικοποίηση στοιχείων πίνακα με constructor. class City char Polh[30]; float Temp[N]; City() for (int i=0;i<n;i++) Temp[i]=0.0; ~City() Εύρεση Μ.Ο μισθών Ν υπαλλήλων. for (i=0; i<n; i++) sum=sum+erg[i].retmisthos(); avg=sum/n; cout<<"\no M.O. einai: "<<avg<<endl; 37
ΧΡΗΣΗ ΤΩΝ ΠΙΝΑΚΩΝ ΜΕΣΑ ΣΕ ΚΛΑΣΕΙΣ Το πρόγραμμα που ακολουθεί ορίζει μία κλάση με το όνομα Student και δεδομένα τον αριθμό μητρώου ενός σπουδαστή και έναν πίνακα όπου αποθηκεύονται βαθμολογίες του. Το πρόγραμμα εμφανίζει τον Μ.Ο. των βαθμολογιών και την μικρότερή αλλά κα την μεγαλύτερη βαθμολογία. const int N=10; class Student int armht; float vathmos[n]; //pinakas san dedomeno Student() //constructor gia arxikopoihsh data sto 0 int i; armht=0; for (i=0; i<n; i++) vathmos[i]=0; void readdata() //methodos eisagoshs A.M. kai vathmwn int i; cout<<"dose A.M.:"; cin >> armht; cout <<"Dose Vathmous: "; for (i=0; i<n; i++) cin>>vathmos[i]; float getavg() //methodos gia ton M.O. int i; float sum=0, avg; for (i=0; i<n; i++) sum+=vathmos[i]; avg=sum/n; return avg; float getmin() //methodos gia mikrotero vathmo int i; float min; min=vathmos[0]; for (i=1; i<n; i++) if (vathmos[i]<min) min=vathmos[i]; return min; float getmax() //methodos gia megalytero vathmo int i; float max; max=vathmos[0]; for (i=1; i<n; i++) 38
if (vathmos[i]>max) max=vathmos[i]; return max; ; Student Stud1; //orismos antikeimenoy Stud1.readData(); cout<<"m.o.: "<<Stud1.getAvg()<<endl; cout<<"megalyteros Vathmos: "<<Stud1.getMax()<<endl; cout<<"mikroteros Vathmos: "<<Stud1.getMin()<<endl; Στο πρόγραμμα που ακολουθεί δηλώνεται ένας πινάκας σαν δεδομένο μιας κλάσης. Κατασκευάζεται ένα αντικείμενο το οποίο κάνει εισαγωγή δεδομένων μέσω της κλάσης. Κατόπιν τα δεδομένα μεταφέρονται σε έναν δεύτερο πίνακα έξω από την κλάση όπου και τυπώνονται με στηλοθεσία. Στο τέλος τυπώνεται το άθροισμα των τιμών που δόθηκαν. #include <iomanip.h> const int MAX=5; //dhlwsh sta8eras class pinakas //dhlwsh klashs int Arr[MAX]; //dhlwsh pinaka san dedomeno void getdata() int i; for(i=0; i<max; i++) cout<<"\ndose "<<i+1<<"o Ari8mo:"; cin>>arr[i]; cout<<"to Arr["<<i<<"]= "<<Arr[i]; Arr[i]+=MAX; //pros8esh stis times ths timhs MAX int retdata(int k) //epistrofh timhs stoixeiou pinaka return Arr[k]; ; //telos klashs pinakas pin1; //dhlwsh antikeimenou pin1 int Arr2[MAX]; //dhlosh 2ou pinaka int i, sum=0; pin1.getdata(); //eisagwgh timwn // metafora timwn apo pinaka se pinaka 39
for(i=0; i<max; i++) Arr2[i]=pin1.retData(i); //ektypwsh me sthlo8esia cout<<"\n\nse ka8e timh proste8hke to MAX"<<endl; cout<<"oi times metafer8hkan ston Arr2[]"<<endl; for(i=0; i<max; i++) sum+=arr2[i]; //ypologismos a8roismatos cout<<endl; cout<<setw(5)<<"to Arr2["<<i<<"]="<<Arr2[i]<<endl; //ektupwsh toy a8roismatos twn timwn cout<<"\n\nto A8roisma twn stoixeiwn toy pinaka Arr2[] einai: "; cout<<sum<<endl<<endl; //telos main ΠΙΝΑΚΕΣ ΜΕ ΑΝΤΙΚΕΙΜΕΝΑ Στο παρακάτω πρόγραμμα καταγράφονται τα στοιχεία 5 εργαζομένων. Με την πληκτρολόγηση του Α.Μ εμφανίζονται τα στοιχεία του συγκεκριμένου εργαζόμενου. Εάν το Α.Μ. δεν υπάρχει τότε το πρόγραμμα θα εμφανίζει μήνυμα λάθους. const int N=5; class Ergazomenoi int armht; char onoma[20]; float misthos; void readdata() //eisagogh stoixeiwn cout<<"dose A.M.: "; cin>>armht; cout<<"dose Onoma: "; cin>>onoma; cout<<"dose Mistho: "; cin>>misthos; void printdata() //ektypwsh stoixeiwn cout<<"a.m.: "<<armht<<endl; cout<<"onoma: "<<onoma<<endl; cout<<"misthos: "<<misthos<<endl; int retam() //epistrofh A.M. return armht; ; 40
Ergazomenoi erg[n]; //pinakas antikeimenwn int i, armht; bool found=false; cout <<"Dose stoixeia "<<N<<" Ergazomenwn: "<<endl; for (i=0; i<n; i++) cout<<endl<<"ergazomenos "<<i+1<<":"<<endl; erg[i].readdata(); //klhsh synarthshs apo ola ta antik cout<<"dose A.M. gia Anazhthsh: "; cin>>armht; i=0; found=false; while (i<n && found==false) if (erg[i].retam()==armht) //eyresh A.M ergazomenwn found=true; //ergazomenos vre8hke else i++; //metrhths mexri to N if (found==true) //typwse ta stoixeia toy ergazomenou erg[i].printdata(); else //o A.M. den vre8hke cout<<"o Ergazomenos den yparxei"<<endl; Σύντομη εξήγηση του προγράμματος. Στο προηγούμενο πρόγραμμα ορίζεται ένας πίνακας αντικειμένων erg τύπου Ergazomenoi. Κατόπιν με ένα βρόχο for, εισάγονται πληροφορίες για κάθε ένα από τα 5 αντικείμενα του πίνακα, με την κλήση της συνάρτησης readdata(). Τέλος, πληκτρολογείται ένας τυχαίος αριθμός μητρώου και αναζητείται στον πίνακα αντικειμένων. Αν υπάρχει, εμφανίζονται οι πληροφορίες για το συγκεκριμένο εργαζόμενο. Αν όχι εμφανίζεται αντίστοιχο μήνυμα. 41
ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ ΒΑΣΙΚΗ ΚΑΙ ΠΑΡΑΓΩΓΕΣ ΚΛΑΣΕΙΣ class logariasmos //basikh klash protected: //prostateymeno dedomeno-melos float ypoloipo; logariasmos() //dhlosh constructor ypoloipo=0; float pareypoloipo() return ypoloipo; ; //telos basikhs klashs class tokoslogar:public logariasmos //paragomenh klash void tokos() //methodos paragomenhs klashs ypoloipo+=ypoloipo*0.1; ; //telos paragomenhs klashs tokoslogar loga; //antikeimeno ths paragomenhs klashs cout <<"Trexon ypoloipo:"<<loga.pareypoloipo()<<endl; loga.katathesi(120.0); cout <<"Trexon ypoloipo:"<<loga.pareypoloipo()<<endl; loga.tokos(); cout <<"Trexon ypoloipo:"<<loga.pareypoloipo()<<endl; //telos ths main Σχηματική παράσταση του προγράμματος. logariasmos tokoslogar Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω παράδειγμα δημιουργήσαμε μια βασική κλάση logariasmos και μία δημόσια παραγόμενη κλάση tokoslogar. Στην main() δημιουργούμε ένα αντικείμενο loga της παράγωγης κλάσης tokoslogar. 42
Το αντικείμενο από την στιγμή που δεν υπάρχει constructor στην κλάση tokoslogar αρχικοποιείται στην τιμή 0 χρησιμοποιώντας τον constructor της βασικής κλάσης logariasmos. Επίσης το αντικείμενο χρησιμοποιεί τις μεθόδους katathesi() και pareypoloipo() της κλάσης logariasmos. To δεδομένο-μέλος έχει δηλωθεί ως protected έτσι ώστε να είναι προσπελάσιμο και από την βασική κλάση στην οποία και ανήκει αλλά και στην παράγωγη (εάν ήταν private θα είχε πρόσβαση σε αυτό μόνο η κλάση στην οποία ανήκει δηλαδή η logariasmos). Η κληρονομικότητα δεν λειτουργεί αντίστροφα, δηλαδή εάν φτιάχναμε στην main() ένα αντικείμενο της βασικής κλάσης π.χ. logariasmos log1 αυτό θα είχε πρόσβαση μόνο στις μεθόδους της κλάσης στην οποία ανήκει και είναι η βασική αλλά όχι και στην μέθοδο tokos() που ανήκει στην παραγόμενη κλάση. ΣΥΝΔΙΑΣΜΟΙ ΠΡΟΣΒΑΣΗΣ class Basic //basikh klash int privmember; //idiotiko dedomeno-melos protected: int protmember; //prostateymeno dedomeno-melos int publmember; //dhmosio dedomeno-melos ; //telos basikhs klashs class ProdA:public Basic //dhmosia paragomenh klash void method() int x; x=privmember; //mh prospelasimo x=protmember; //prospelasimo x=publmember; //prospelasimo ; //telos klashs ProdA class ProdB:private Basic //idiotika paragomenh klash void method() int x; x=privmember; //mh prospelasimo x=protmember; //prospelasimo x=publmember; //prospelasimo ; //telos klashs ProdB int y,z; ProdA anta; //antikeimeno ths paragomenhs ProdA 43
y=anta.privmember; //mh prospelasimo y=anta.protmember; //mh prospelasimo y=anta.publmember; //prospelasimo ProdB antb; //antikeimeno ths paragomenhs ProdB z=antb.privmember; //mh prospelasimo z=antb.protmember; //mh prospelasimo z=antb.publmember; //mh prospelasimo //telos ths main Σχηματική παράσταση του προγράμματος. Basic ProdA ProdB Σύντομη εξήγηση του προγράμματος. Στο παραπάνω πρόγραμμα ορίζεται μία βασική κλάση Basic και δύο παραγόμενες κλάσεις, η μία δημόσια παραγόμενη ProdA και η άλλη ιδιωτικά ProdB. Στην βασική κλάση δηλώνονται τρία δεδομένα-μέλη, το πρώτο σαν ιδιωτικό, το δεύτερο σαν προστατευμένο και το τρίτο σαν δημόσιο. Μέθοδοι των παράγωγων κλάσεων μπορούν να έχουν πρόσβαση σε προστατευμένα και δημόσια δεδομένα-μέλη της βασικής κλάσης, όχι όμως σε ιδιωτικά. Αντικείμενα παράγωγων κλάσεων δεν μπορούν να έχουν πρόσβαση σε προστατευμένα και ιδιωτικά δεδομένα-μέλη της βασικής κλάσης. Αντικείμενα της παράγωγης κλάσης που παράγεται δημόσια (ProdA) μπορούν να έχουν πρόσβαση σε δημόσια δεδομένα-μέλη της βασικής κλάσης. Αντικείμενα παράγωγης κλάσης που παράγεται ιδιωτικά (ProdB) δεν μπορούν να έχουν πρόσβαση ούτε στα δημόσια δεδομένα-μέλη της βασικής κλάσης. Εάν δεν δηλώσουμε τον τρόπο προσπέλασης κατά την δήλωση παραγωγής μιας κλάσης τότε θεωρείται ότι η κλάση αυτή παράγεται ιδιωτικά (private). 44
ΥΠΕΡΦΟΡΤΩΣΗ ΣΥΝΑΡΤΗΣΕΩΝ class logariasmos //basikh klash protected: //prostateymeno dedomeno-melos float ypoloipo; logariasmos() //constructor x.o. ypoloipo=0; float pareypoloipo() return ypoloipo; ; //telos basikhs klashs class tokoslogar:public logariasmos //paragomenh klash tokoslogar():logariasmos() tokoslogar(float ypoloipo):logariasmos(ypoloipo) void tokos() //methodos paragomenhs klashs ypoloipo+=ypoloipo*0.1; void katathesi(float poso) if(poso>0) //elegxos arnhtikoy posou logariasmos::katathesi(poso); //yperfortosh else cout<<"mh egkyro poso"<<endl; void analhpsh(float poso) if(poso>0) //elegxos arnhtikoy posou logariasmos::analhpsh(poso); //yperfortosh else cout<<"mh egkyro poso"<<endl; ; //telos paragomenhs klashs tokoslogar t1; //antikeimeno ths paragoghs klashs t1.katathesi(100); cout<<"neo ypoloipo toy t1= "<<t1.pareypoloipo()<<endl; t1.katathesi(-30); cout<<"neo ypoloipo toy t1= "<<t1.pareypoloipo()<<endl; t1.analhpsh(50); 45
cout<<"neo ypoloipo toy t1= "<<t1.pareypoloipo()<<endl; t1.analhpsh(-45); cout<<"neo ypoloipo toy t1= "<<t1.pareypoloipo()<<endl; //telos ths main Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα έχουμε φτιάξει μεθόδους με το ίδιο όνομα και στην βασική logariasmos και στην παραγόμενη κλάση tokoslogar. Αυτό το κάνουμε για να προσθέσουμε ένα τμήμα ελέγχου μέσα στις μεθόδους analhpsh() και katathesi() χωρίς να επηρεαστούν οι αντίστοιχες μέθοδοι της βασικής κλάσης. Στην main() φτιάχνουμε ένα αντικείμενο t1 της παράγωγης κλάσης tokoslogar όπου κάνει ανάληψη αλλά και κατάθεση με θετικό και αρνητικό ποσό. Στην εντολή t1.katathesi(100); καλείται η μέθοδος katathesi() της παραγόμενης κλάσης όπου και γίνεται ο έλεγχος για το αν το ορισμα είναι θετικό. Εάν το ποσό είναι θετικό τότε καλείται η μέθοδος katathesi() της βασικής κλάσης με την εντολή logariasmos::katathesi(poso); Το ίδιο ισχύει και για την μέθοδο analhpsh(). Είναι πολύ σημαντικό να γνωρίζουμε ότι μέσα στην μέθοδο της παραγόμενης κλάσης για να καλέσουμε την αντίστοιχη με το ίδιο όνομα της βασικής κλάσης θα πρέπει να χρησιμοποιούμε τον τελεστή διάκρισης εμβέλειας :: γιατί αλλιώς η μέθοδος καλεί τον εαυτό της με όχι και τόσο επιθυμητά αποτελέσματα για το πρόγραμμα. Επίσης βλέπουμε και την δήλωση και χρήση των συναρτήσεων εγκατάστασης (constructor) και στην παράγωγη κλάση tokoslogar όπου για να αρχικοποιήσουμε το δεδομένο-μέλος ypoloipo της βασικής συνάρτησης logariasmos, ο constructor της παράγωγης κλάσης (με όρισμα ή χωρίς όρισμα ) καλεί τον αντίστοιχο της βασικής. 46
CONSTRUCTORS ΣΕ ΒΑΣΙΚΗ ΚΑΙ ΠΑΡΑΓΟΜΕΝΗ ΚΛΑΣΗ class animal //vasikh klash protected: float age; bool male; int weight; animal () animal (float i, bool j, int k) //constructor me 3 orismata age = i; male = j; weight = k; class cat:public animal //paragomenh klash char name[10]; cat () // constructor me 4 orismata cat (float a, bool b, int c, char d[]):animal (a, b, c) strcpy(onoma, d); Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω τμήμα ενός προγράμματος φαίνονται δύο κλάσεις. Η βασική που είναι η animal και η παραγόμενη που είναι η cat. Στην βασική κλάση έχουμε δημιουργήσει έναν constructor με 3 ορίσματα animal(float i,bool j,int k). Τα ορίσματα αφορούν στην ηλικία, το φύλλο και το βάρος του ζώου. Στην παραγόμενη κλάση ορίζουμε έναν constructor με 4 ορίσματα cat(float a, bool b,int c, char d[]) που αφορούν σε όλα της βασικής και σε ένα που ορίζουμε στην παραγόμενη κλάση και αφορά το όνομα του ζώου. Έτσι ώστε αν δημιουργήσουμε ένα αντικείμενο cata της κλάσης cat και δώσουμε 4 ορίσματα, τα τρία θα τα αρχικοποιεί ο constructor της βασικής και το ένα αυτός της παραγόμενης. 47
ΕΠΙΠΕΔΑ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑΣ class vehicle //vasikh klash protected: int rodes; char timoni[10]; void start() void stop() void turn() ; //telos vasikhs class auto:public vehicle //paragomenh apo thn vasikh protected: int portes; char motor[20]; ; //telos paragomenhs class truck:public auto //paragomenh apo thn paragomenh char flatbed[10]; void liftflatbed() ; //telos paragomenhs Σχηματική παράσταση του προγράμματος. vehicle auto truck Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω τμήμα ενός προγράμματος φαίνονται τρεις κλάσεις. Η βασική είναι η vehicle από την οποία παράγεται η auto, η οποία κληρονομεί χαρακτηριστικά και μεθόδους από την vehicle. Κατόπιν φαίνεται η truck η οποία κληρονομεί χαρακτηριστικά και μεθόδους από την auto αλλά και από την vehicle. Ένα αντικείμενο της κλάσης truck έχει πρόσβαση στις μεθόδους και της auto και της vehicle. 48
Ένα αντικείμενο της κλάσης auto έχει πρόσβαση στις μεθόδους της vehicle, αλλά όχι σε αυτές της truck. Ένα αντικείμενο της κλάσης vehicle έχει πρόσβαση μόνο στις μεθόδους της κλάσης του. Αυτό συμβαίνει γιατί όπως έχουμε πει η έννοια της κληρονομικότητας δεν λειτουργεί αντίστροφα. ΠΟΛΛΑΠΛΗ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ class screen //proth vasikh klash void showscreen(void); protected: char type[32]; long colors; int x_resol; int y_resol; ; class motherboard //deyterh vasikh klash void showmotherboard(void); protected: char processor[15]; int speed; int RAM; ; //pollaplh klhronomikothta class computer:public screen, public motherboard void showcomputer(void); char name[64]; int hdd; float floppy; ; Σχηματική παράσταση του προγράμματος. screen motherboard computer Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα δηλώνονται δύο κλάσεις screen και motherboard από τις οποίες παράγεται μία κλάση computer η οποία κληρονομεί χαρακτηριστικά και μεθόδους και των δύο κλάσεων. 49
ΠΕΡΙΕΚΤΙΚΟΤΗΤΑ #include <string.h> class logariasmos //klash logariasmos protected: float ypoloipo; logariasmos() ypoloipo=0; float pareypoloipo() return ypoloipo; ; //telos klashs class Pelaths //klash pelaths int armht; char onoma[20]; //antikeimeno ths klashs logariasmos logariasmos log1; Pelaths() Pelaths(int armht1,char onoma1[]) armht=armht1; strcpy(onoma,onoma1); void parexrhma() float poso; cout<<"dose POSO ANALHPSIS:"; cin>>poso; //klhsh synarthshs apo klash logariasmos log1.analhpsh(poso); void valexrhma() float poso; cout<<"dose POSO KATATHESIS:"; cin>>poso; //klhsh synarthshs apo klash logariasmos log1.katathesh(poso); void anaforaypoloipou() cout<<"to TREXON YPOLOIPO EINAI: " <<log1.pareypoloipo()<<endl; 50
; //telos klashs Pelaths P1; P1.anaforaYpoloipou(); P1.valeXrhma(); P1.anaforaYpoloipou(); P1.pareXrhma(); P1.anaforaYpoloipou(); //telos main Σχηματική παράσταση του προγράμματος Class logariasmos Class Pelaths Log1 Αντικείμενο της κλάσης logariasmos μέσα στην κλάση Pelaths Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα βλέπουμε την σχέση της περιεκτικότητας ανάμεσα σε δύο ανεξάρτητες κλάσεις logariasmos και Pelaths. Κατασκευάζουμε ένα αντικείμενο log1 της κλάσης logariasmos μέσα στην κλάση Pelaths. Με αυτόν τον τρόπο το αντικείμενο log1 μπορεί να εκτελεί μεθόδους της κλάσης logariasmos μέσα από τη κλάση Pelaths. 51
ΣΧΗΜΑΤΙΚΗ ΠΑΡΑΣΤΑΣΗ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑΣ ΟΧΗΜΑ Ρόδες Τιμόνι Ξεκινά() Σταματά() Στρίβει() Βασική κλάση όχημα παράγωγες κλάσεις από όχημα ΑΥΤΟΚΙΝΗΤΟ ΠΟΔΗΛΑΤΟ ΜΗΧΑΝΗ Μηχανή Πόρτες Συμπλέκτης Σταντ Μηχανή Σταντ Συμπλέκτης ΦΟΡΤΗΓΟ Καρότσα Ανατροπή() ΕΠΙΒΑΤΙΚΟ Πίσω πόρτα ΛΕΩΦΟΡΕΙΟ Πολλά καθίσματα παράγωγες κλάσεις από αυτοκίνητο 52
ΥΠΕΡΦΟΡΤΩΣΗ ΤΕΛΕΣΤΩΝ (παραδείγματα) ΥΠΕΡΦΟΡΤΩΣΗ ΤΟΥ ΤΕΛΕΣΤΗ ΡΟΗΣ << #include <process.h> void main () int a,b,x; while(1) cout<<"\n=================================" ; cout<<"\ndose arithmo H 0 gia exodo:"; cin>>a; if(a==0) cout<<"\n -telos programmatos-\n"; exit(0); cout<<"\nose plithos theseon gia metakinhsh :"; cin>>b; x=a<<b; // metakinhsh toy arithmou cout<<"\no arithmos poy edoses einai : " ; cout<<a; cout<<"\nplithos bits poy metakinhthikan :"; cout<<b; cout<<"\no neos arithmos einai :"; // edo kai se oles tis cout typonei times cout<<x<<endl; Σύντομη εξήγηση του προγράμματος. Στο παραπάνω πρόγραμμα χρησιμοποιούμε τον τελεστή ροής << στην έκφραση a<<b για να μετακινήσουμε τα δυαδικά ψηφία προς τα αριστερά ενός δεκαδικού αριθμού a, τόσες θέσεις όσες δηλώνει ο αριθμός που βρίσκεται δεξιά του τελεστή δηλαδή ο αριθμός b. O τελεστής θα λειτουργήσει με υπερφόρτωση μόνο στην παράσταση x=a<<b; Σε όλες τις άλλες γραμμές του κώδικα θα λειτουργεί σαν τελεστής ροής εισόδου εξόδου μαζί με τα αντικείμενα cin και cout. Στην επανάληψη while(1) το 1 μέσα στην παρένθεση είναι μία σταθερά μεγαλύτερη του 0 και αντικαθιστά την συνθήκη (1>0), δηλαδή επαληθεύεται διαρκώς. Άρα οι εντολές της while εκτελούνται ασταμάτητα, εωσότου εισάγουμε τον αριθμό 0 όπου εκεί ενεργεί η συνάρτηση exit(0) η οποία προκαλεί άμεση διακοπή του προγράμματος. Η exit() βρίσκεται μέσα στο αρχείο κεφαλίδας process.h το οποίο και συμπεριλαμβάνουμε στην αρχή του προγράμματος. 53
Έξοδος του προγράμματος: αν a=3 (11) 2 και b=2 τότε το x γίνεται (1100) 2 12 αν a=12 (1100) 2 και b=3 τότε το x γίνεται (1100000) 96 αν a=-2 (10000010) 2 και b=4 τότε το x γίνεται (10100000) -32 ΥΠΕΡΦΟΡΤΩΣΗ ΤΟΥ ΤΕΛΕΣΤH ΑΥΞΗΣΗΣ ΚΑΤΑ 1 ++. # include <iostream.h> class metritis int met; metritis() //constructor met=0; void calc_met() //func gia afkshsh met ++met; int get_met() //func gia lhpsh timhs met return met; ; metritis met1,met2; //2 antikeimena me timh 0 int m,k,i; //topikes metavlhtes i=0; ++i; //afkshsh kata 1 ++i; //afkshsh kata 1 cout<<"\nmetriths i="<<i; cout<<"\n\n"; m=met1.get_met(); //apodosh ths timhs met (0) sto m k=met2.get_met(); //apodosh ths timhs met (0) sto k cout<<"\nmetriths met1= "<<m; cout<<"\nmetriths met2= "<<k; cout<<endl; met1.calc_met(); //afkshsh kata 1 toy met1 (1) met2.calc_met() ; //afkshsh kata 1 toy met2 (1) met1.calc_met(); //afkshsh kata 1 toy met1 (2) met1.calc_met() ; //afkshsh kata 1 toy met1 (3) //ektyposh ths timhs tou met1 cout<<"\netriths met1="<<met1.get_met(); //ektyposh ths timhs tou met2 cout<<"\netriths met2="<<met2.get_met(); //prosthesi kai apodosh timhs sto k k=met1.get_met()+met2.get_met(); cout<<"\nto athroisma einai :"<<k<<endl; //ektyposh toy k 54
Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα βλέπουμε ότι χρησιμοποιούμε τον τελεστή ++ και στην τοπική μεταβλητή i της main αλλά και στο δεδομένο μέλος met της κλάσης metritis ο οποίος λειτουργεί όπως πρέπει σε αυτές. Αυξάνει δηλαδή κατά ένα δύο φορές την i μέσα στην main αλλά και με την κλήση της calc_met() από τα αντικείμενα met1 και met2 αυξάνει την τιμή του δεδομένου μέλους met για κάθε αντικείμενο. Στο τέλος προσθέτει τις δύο τιμές και τις εκχωρεί εκ νέου στην μεταβλητή k. Εάν γράψουμε ++met1 προσπαθώντας να αυξήσουμε την τιμή του αντικειμένου ο compiler θα μας δώσει λάθος. Γι αυτόν τον λόγο χρησιμοποιούμε την λέξη κλειδί operator με τον τελεστή ++ αντί της συνάρτησης calc_met(). Τώρα εάν χρησιμοποιήσουμε την έκφραση ++met1; ο compiler θα αυξήσει την τιμή του αντικειμένου χωρίς λάθος. Αυτό φαίνεται στο πιο κάτω πρόγραμμα. # include <iostream.h> ///////////////////////////////////////////////////////// void operator ++() //yperfortosh telesth ++ ++met; int get_met() //func gia lhpsh timhs met return met; ; /////////////////////////////////////////////////////////// cout<<"\nmetriths met2= "<<k; cout<<endl; ++met1; //afkshsh me yperfortosh ++met2; //afkshsh me yperfortosh ++met1; //afkshsh me yperfortosh ++met1; //afkshsh me yperfortosh ////////////////////////////////////////////////////////////// cout<<"\nto athroisma einai :"<<k<<endl; //ektyposh toy k Στο πιο πάνω παράδειγμα έχουμε προθεματική χρήση του operator. Για επιθεματική χρήση του operator η αλλαγή είναι πιο κάτω. 55
# include <iostream.h> ///////////////////////////////////////////////////////// //epithematikh yperfortosh telesth ++ void operator ++(int) met++; int get_met() //func gia lhpsh timhs met return met; ; /////////////////////////////////////////////////////////// cout<<"\nmetriths met2= "<<k; cout<<endl; met1++; //afkshsh me epithematikh yperfortosh met2++; //afkshsh me epithematikh yperfortosh met1++; //afkshsh me epithematikh yperfortosh met1++; //afkshsh me epithematikh yperfortosh ////////////////////////////////////////////////////////////// cout<<"\nto athroisma einai :"<<k<<endl; //ektyposh toy k ΠΡΟΘΕΜΑΤΙΚΗ ΚΑΙ ΕΠΙΘΕΜΑΤΙΚΗ ΥΠΕΡΦΟΡΤΩΣΗ class test unsigned int met; test() //constructor xoris orisma met = 0; test(int x) //constructor me orisma met=x ; test operator ++() //prothematikh morfh return test(++met); test operator ++(int) //epithematikh morfh return test(met++); 56
; int get_met() return met; test t1,t2 ; cout<<"\nt1 = "<<t1.get_met(); //(t1=0) cout<<"\nt2 = "<<t2.get_met(); //(t2=0) ++t1; //prothamatikh yperfortosh (t1=1) ++t1; //prothamatikh yperfortosh (t1=2) t2=++t1; // (t1=3, t2=3) cout<<"\nt1 = "<<t1.get_met(); cout<<"\nt2 = "<<t2.get_met(); t2=t1++; //epithamatikh yperfortosh (t2=3,t1=4) t2=t1++; //epithamatikh yperfortosh (t2=4,t1=5) cout<<"\nt1 = "<<t1.get_met(); cout<<"\nt2 = "<<t2.get_met(); cout<<"\n\n"; Εξοδος: 1 Ο cout t1=0, t2=0 2 Ο cout t1=3, t2=3 3 Ο cout t1=5, t2=4 ΥΠΕΡΦΟΡΤΩΣΗ ΑΡΙΘΜΗΤΙΚΟΥ ΤΕΛΕΣΤΗ + class logariasmos float ypoloipo; logariasmos() //dhlosh constructor ypoloipo=0; ~logariasmos() //dhlosh destructor //orismos synarthshs gia yperfortwsh //telesth prostheshs logariasmos operator+ (logariasmos a) logariasmos sum; sum.ypoloipo=ypoloipo+a.ypoloipo; return sum; void analhpsh(float poso) if (poso<=ypoloipo) 57
ypoloipo=ypoloipo-poso; else cout<<"prosoxh!!!!!!"<<endl; cout<<"to poso ths analhpsis einai megalytero apo to ypoloipo"<<endl; void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; ; logariasmos log1,log2,log3; cout<<endl; cout<<"dhmiourgia 3 antikeimenwn"<<endl; cout<<"enarxh synallagwn"<<endl; cout<<"=========================================="<<endl; cout<<"arxika ypoloipa"<<endl; cout<<"log1: "<<log1.pareypoloipo()<<" Euro"<<endl; cout<<"log2: "<<log2.pareypoloipo()<<" Euro"<<endl; cout<<"log3: "<<log3.pareypoloipo()<<" Euro"<<endl; cout<<"=========================================="<<endl; cout<<"=========================================="<<endl; cout <<"Katathesi 100 Euro apo to log1"<<endl; log1.katathesi(100.0); cout <<"Katathesi 200 Euro apo to log2"<<endl; log2.katathesi(200.0); cout<<"=========================================="<<endl; cout<<"ta ypoloipa eginan"<<endl; cout<<"log1: "<<log1.pareypoloipo()<<" Euro"<<endl; cout<<"log2: "<<log2.pareypoloipo()<<" Euro"<<endl; cout<<"log3: "<<log3.pareypoloipo()<<" Euro"<<endl; cout<<"=========================================="<<endl; cout<<"=========================================="<<endl; cout <<"Analhpsh 70 Euro apo to log1"<<endl; log1.analhpsh(70.0) ; cout<<"=========================================="<<endl; cout <<"Ta ypoloipa twra einai:"<<endl; cout<<"log1: "<<log1.pareypoloipo()<<" Euro"<<endl; cout<<"log2: "<<log2.pareypoloipo()<<" Euro"<<endl; cout<<"log3: "<<log3.pareypoloipo()<<" Euro"<<endl; cout<<"=========================================="<<endl; cout<<"prosthesi twn ypoloipwn log1 me to log2"<<endl; cout<<"=========================================="<<endl; log3=log1+log2; cout <<"Ta ypoloipa twra einai:"<<endl; cout<<"log1: "<<log1.pareypoloipo()<<" Euro"<<endl; cout<<"log2: "<<log2.pareypoloipo()<<" Euro"<<endl; 58
cout<<"log3: "<<log3.pareypoloipo()<<" Euro"<<endl; cout<<"=========================================="<<endl; cout<<"=========================================="<<endl; cout<<"telos synallagwn"<<endl; cout<<"=========================================="<<endl; cout<<endl; Σύντομη εξήγηση του προγράμματος. Εδώ έχουμε την χρήση του operator για υπερφόρτωση του τελεστή πρόσθεσης +. Στη συνάρτηση υπερφόρτωσης δηλώνουμε ένα αντικείμενο sum που θα δεχθεί το αποτέλεσμα της άθροισης, θα επιστραφεί στο πρόγραμμα και θα αποδοθεί στο αντικείμενο στο οποίο εκχωρείται η τιμή της άθροισης και είναι το log3. Επίσης στην συνάρτηση υπερφόρτωσης χρησιμοποιούμε ως όρισμα το αντικείμενο που βρίσκεται δεξιά του τελεστή + στην προταση που βρίσκεται μέσα στη main() (log3=log1+log2), δηλαδή το αντικείμενο log2. Επειδή η συνάρτηση υπερφόρτωσης ανήκει και στο αντικείμενο που βρίσκεται αριστερά από τον τελεστή, δηλαδή στο log1 η αναφορά στο δεδομένο-μέλος της κλάσης logariasmos γίνεται άμεσα. Το αποτέλεσμα είναι να προσθέτουμε τα αντικείμενα σαν να ήταν μεταβλητές και να έχουμε αποτέλεσμα το άθροισμα των δεδομένων-μελών ypoloipo. ΥΠΕΡΦΟΡΤΩΣΗ ΣΥΓΚΡΙΤΙΚΟΥ ΤΕΛΕΣΤΗ > class logariasmos float ypoloipo; logariasmos() ypoloipo=0; logariasmos(float arxiko_ypoloipo) ypoloipo=arxiko_ypoloipo; ~logariasmos() void analhpsh(float poso) if (poso<=ypoloipo) ypoloipo=ypoloipo-poso; else cout<<"prosoxh!!!!!!"<<endl; cout<<"poso megalytero apo to ypoloipo"<<endl; 59
void katathesi(float poso) ypoloipo+=poso; float pareypoloipo() return ypoloipo; //operator me sygritiko telesth bool operator >( logariasmos log) if (ypoloipo>log.ypoloipo) return true; else return false; ; //telos klashs logariasmos log1(200.0), log2(120.0), log3(50.0), log4(110.0); //yperfortvsh gia thn sygkrish logariasmon if (log1>log2) cout<< log1 > log2 <<endl; else cout<< log2 >= log1 <<endl; if (log3>log4) cout<< log3 > log4 <<endl; else cout<< log4 >= log3 <<endl; Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα χρησιμοποιούμε υπερφόρτωση του συγκριτικού τελεστή > για να μπορούμε να συγκρίνουμε δύο λογαριασμούς. ΥΠΕΡΦΟΡΤΩΣΗ ΤΟΥ ΤΕΛΕΣΤΗ ΚΛΗΣΗΣ ΣΥΝΑΡΤΗΣΗΣ () // doublestatementclass.h class doublestatement //dhlwsh klashs doublestatement(); int operator() (int,int); //yperfortwsh ths parentheshs int ArrayA[10][10]; //pinakas ws dedomeno-melos ; 60
// overl_parentesis.cpp #include "doublestatementclass.h" //symperilhpsi toy arxeiou ths klashs doublestatement::doublestatement() //constructor xwris orisma for(int loopa=0; loopa<10; ++loopa) for(int loopb=0; loopb<10; ++loopb) ArrayA[loopA][loopB]=loopB; int doublestatement::operator() (int a, int b) //orismos yperfortwshs return ArrayA[a][b]; int main() doublestatement ds1; //antikeimeno cout<<"to stoixeio ArrayA[3][6] exei thn timh: "<<ds1(2,6)<<endl; //cout<<"to stoixeio ArrayA[3][6] exei thn timh: "<<ds1[3][6]<<endl; return 0; Σύντομη εξήγηση του προγράμματος. Στο πιο πάνω πρόγραμμα χρησιμοποιούμε υπερφόρτωση του τελεστή παρένθεσης ή αλλιώς τελεστή κλήσης συνάρτησης. Στο αρχείο κεφαλίδας δηλώνουμε την κλάση doublestatement και στο αρχείο του προγράμματος ορίζουμε της συναρτήσεις της κλάσης. Ορίζουμε δηλαδή τον constructor ο οποίος αρχικοποιεί με τιμές από το 1-9 όλλες τις γραμμές του πίνακα ArrayA, αλλά και την συνάρτηση με την οποία γίνεται η υπερφόρτωση του τελεστή κλήσης συνάρτησης. Μέσα στην main() δηλώνουμε ένα αντικείμενο της κλάσης και εξάγουμε στην οθόνη την τιμή ενός συγκεκριμένου στοιχείου του πίνακα ArrayA, όχι όμως με την γνωστή μορφή αλλά με την μορφή που έχουν οι πίνακες σε άλλες γλώσσες προγραμματισμού δηλαδή ds1(2,6). 61
ΔΕΙΚΤΕΣ (παραδείγματα) ΔΕΙΚΤΕΣ 1 int a,b; // δήλωση μεταβλητών a και b int *p; // δήλωση δείκτη p a=20; // η τιμή της a=20 &a; // η διεύθυνση της a= 0x0012FF7C p=&a; // η διεύθυνση του p= 0x0012FF7C (1) *p; // η τιμή του a=20 περνά στον p (2) b=*p; // η τιμή του p=20 περνά στη b (3) cout<<"h a einai:"<<a<<" kai h b einai:"<<b<<endl; p (1) 12FF7C a 20 (2) 12FF7C b (3) 20 στον δείκτη p εκχωρείται ως τιμή η διεύθυνση της a (o p δείχνει στην a), στην b εκχωρείται ως τιμή το περιεχόμενο της μεταβλητής a της οποίας την διεύθυνση έχει ως τιμή ο p (*p δηλ το περιεχόμενο της a). ΔΕΙΚΤΕΣ 2 int a=2, b=5; int *p, *q; p=&a; // η διεύθυνση του a στον p (1) q=&b; // η διεύθυνση του b στον q (1) p=q; //όπου δείχνει ο q να δείχνει και ο p (2) *p=*q; //το περιεχόμενο της b που δείχνει o q //εκχωρείται ως περιεχόμενο στην a που δείχνει ο p.(3) (1) p a p a πριν 2 2 μετά q b q b 5 5 O p δείχνει στην a O q δείχνει στην b πριν (2) p a p a 2 2 μετά q b q b 5 5 Όπου δείχνει ο q να δείχνει και ο p 62