Αντικειμενοστρεφής Προγραμματισμός Κλάσεις και άλλα θέματα Απόστολος Ζάρρας * βασισμένα και σε δουλειά του Π. Βασιλειάδη
2 Θεματολόγιο Κλάσεις
3 Παράδειγμα κλάσης Stack: μια δομή αποθήκευσης δεδομένων με τρόπο σειριακό. LIFO: Last In, First Out, ήτοι, μπορούμε να ανακτήσουμε πρώτο, το αντικείμενο που αποθηκεύσαμε την τελευταία φορά. Λειτουργίες push και pop για αποθήκευση και διαγραφή δεδομένων. Λειτουργία read για διάβασμα της τελευταίας τιμής.
4 Stack: πώς λειτουργεί 4 Push(4)
5 Stack: πώς λειτουργεί 4 Push(8) 8
6 Stack: πώς λειτουργεί 4 8 Push(12) 12 Η read() επιστρέφει 12
7 Stack: πώς λειτουργεί 4 8 Pop() 12
8 Stack: πώς λειτουργεί 4 8 Push(16) 1616
9 File: stack1.h const int STACK_SIZE = 100; class Stack1{ private: int count; int data [STACK_SIZE]; public: void init(void); void push(const int &value); int pop(); int read(); };
10 File: stack1.cpp #include #include "stack1.h" //Initialization: simply set the number of //included items to zero void Stack1::init(void){ count = 0; }
11 File: stack1.cpp //Add an item, abort if there is no room void Stack1::push (const int &value){ if (count == STACK_SIZE) cout << "There is no room for more values\n"; count++; data[count] = value; }
12 File: stack1.cpp //Remove an item. Beware for an empty stack //Moreover, we do not dispose of unused memory int Stack1::pop(){ int result; if (count ==0) cout << "The stack is empty; nothing to pop\n"; else{ result = data[count]; --count; } return (result); }
13 File: stack1.cpp //Read the top number from the stack int Stack1::read(){ if (count ==0){ cout << "The stack is empty; nothing to pop\n"; } return (data[count]); }
14 File: main.cpp #include "stack1.h" #include main(){ Stack1 myStack; myStack.init(); myStack.push(4); myStack.push(8); myStack.push(12); cout << "Expect 12 " << myStack.read() <<"\n"; myStack.pop(); cout << "Expect 8 " << myStack.read() <<"\n"; } Ορισμός αντικειμένουΚλήση Μεθόδου
15 makefiles Τα makefiles ρυθμίζουν τον τρόπο με τον οποίο συνδέουμε πολλά αρχεία μεταξύ τους Όταν μεταφράζουμε τον πηγαίο (source) κώδικα, ο μεταγλωττιστής παράγει ένα αρχείο με τελικό (object) κώδικα. Ο linker συνδέει τα αρχεία τελικού κώδικα με τον τελικό κώδικα από τις βιβλιοθήκες και παράγει το εκτελέσιμο.
16 makefiles Main.cpp Compiler Stack1.cpp Stack1.h Stack1.o Other libraries Linker Executable
17 makefiles Το αρχείο makefile (ή σχεδόν ισοδύναμα και Makefile) περιέχει εντολές για το πώς θα συνδέσουμε και θα μεταγλωττίσουμε τα αρχεία μας. Μερικές οδηγίες (options ή directives): # This is a comment # Options for the compilation of C, C++ programs: # -O Optimize object code # -c Compile and assemble, but do not link # -o Place the output into
18 Χρήση Τα περιεχόμενα του τρέχοντος directory είναι: stack1.h, stack1.cpp, main.cpp, makefile Η μεταγλώττιση γίνεται ως εξής: make main
19 File: makefile # stack1.o DEPENDS on stack1.h and stack1.cpp # Still, we create only the.o file and do not # link it to an executable # main DEPENDS on the stack1.o[bject] file and # main.cpp # We compile it and we produce the executable # main main: stack1.o main.cpp g++ stack1.o main.cpp -o main stack1.o: stack1.h stack1.cpp g++ -O -c stack1.cpp
20 Εναλλακτικά Ένας πιο απλός τρόπος για να κάνετε compile κατ’ ευθείαν το πρόγραμμά σας: g++ -o main main.cpp stack1.cpp
21 Ορισμός μιγαδικών class Complex { private: double re, im; public: void set (double r, double i); Complex operator + (Complex c); int operator == (Complex c); };
22 Ορισμός και χρήση αντικειμένων Complex a, b, c; a.set(3, 4); b.set(1, 0); c = a + b; if (c == b + a) cout << "correct.\n"; else cout << "mistake!\n";
23 Ορισμός μεθόδων void Complex::set (double r, double i) { re = r; im = i; }
24 Ορισμός τελεστών Complex Complex::operator + (Complex c) { Complex result; result.set(re + c.re, im + c.im); return result; } int Complex::operator == (Complex c) { return (re == c.re && im == c.im); }
25 Κλάσεις και εμβέλεια Complex Complex::operator + (Complex c); Complex c1, c2, c; c = c1 + c2; Complex Complex::operator + (double d); double d; c = c1 + d; c = d + c2; // wrong!!! z 1 + z 2 z + rr + z
26 Κλάσεις και εμβέλεια class Complex { private: double re, im; public: void set (double r, double i); //... } int main () { Complex c; c.set(1, 0); // correct c.re = 1; // wrong }
27 Κλάσεις και εμβέλεια Απόκρυψη πληροφοριών Ο προγραμματιστής ορίζει τα πεδία των αντικειμένων που θα είναι ορατά από τον υπόλοιπο κόσμο Καλύτερη δόμηση προγραμμάτων Ανεξαρτησία διαπροσωπείας και υλοποίησης Μειονεκτήματα Πολλές φορές απαιτούνται συναρτήσεις πρόσβασης στα μη ορατά πεδία double Complex::getRe ();
28 Ένα καλύτερο stack… class StackInt{ private: struct StackElement { int data; StackElement * next; }; StackElement * top; public: void init(); void push (int n); void pop (); int read (); void empty (); void print (); };
29 Ένα καλύτερο stack void StackInt::init(){ top = NULL; } void StackInt::push (int n) { StackElement *pushed= new StackElement; pushed->data = n; pushed->next = top; top = pushed; }
30 Ένα καλύτερο stack top NULL pushed NULL pushed = new StackElement pushed -> next = top top = pushed top
31 Ένα καλύτερο stack top 1000 pushed NULL pushed = new StackElement next = top top = pushed top
32 Ένα καλύτερο stack 1000 NULL top
33 Ένα καλύτερο stack void StackInt::pop (){ StackElement * popped = top; if (popped == NULL) { cerr << "Error: Empty stack\n"; exit(EXIT_FAILURE); } top = top->next; delete popped; } int StackInt::read (){ if (top == NULL) { cerr << "Error: Empty stack\n"; exit(EXIT_FAILURE); } return top->data; }
34 Ένα καλύτερο stack 1000 NULL top top = top->next top popped popped = top
35 Ένα καλύτερο stack 1000 NULL top popped delete popped
36 Ένα καλύτερο stack 1000 NULL top popped
37 Ένα καλύτερο stack void StackInt::empty () { while (top != NULL) pop(); } void StackInt::print () { cout << "The stack contains: "; for (StackElement *p=top; p!=NULL; p=p->next) cout data << ", "; cout << "no (more) data.\n"; }