====== Interfaces ====== Η C++ δεν διαθέτει //interfaces// με τον αυστηρά ορισμένο τρόπο που αυτά ορίζονται στη Java. Αντ' αυτού υλοποιεί την λειτουργικότητα των //interfaces// μέσω //[[cpp:polymorphism#pure_virtual_συναρτήσεις_και_abstract_κλάσεις|abstract]]// κλάσεων, δηλαδή κλάσεων που δεν μπορούν να δώσουν αντικείμενα. Στο παράδειγμα που ακολουθεί ορίζουμε το interface Stack το οποίο μπορεί να αποθηκεύει ακεραίους. Η //abstract base class Stack// έχει δύο υποκλάσεις την κλάση //ArrayStack// που υλοποιεί τη στοίβα μέσω ενός πίνακα και την κλάση //LinkedStack// που υλοποιεί τη στοίβα μέσω απλά συνδεδεμένης λίστας. #include using namespace std; #ifndef __STACK_H__ #define __STACK_H__ class Stack { public: virtual int size()=0; virtual void push(int o)=0; virtual int pop()=0; virtual int top()=0; }; #endif #include using namespace std; #include "Stack.h" #ifndef __ARRAYSTACK_H__ #define __ARRAYSTACK_H__ class ArrayStack : public Stack { int *array; int stackSize, capacity; public: ArrayStack(int capacity=16); int size(); void push(int o); int pop(); int top(); }; #endif #include "ArrayStack.h" ArrayStack::ArrayStack(int cap) { capacity = cap; stackSize = 0; array = new int[capacity]; } int ArrayStack::size() { return stackSize; } void ArrayStack::push(int o) { if(stackSize==capacity) { int *_array = new int[2*capacity]; for(int i=0; i #include using namespace std; #include "Stack.h" #ifndef __LINKEDSTACK_H__ #define __LINKEDSTACK_H__ class LinkedNode { int element; LinkedNode *next; public: LinkedNode(LinkedNode *nxt, int e); LinkedNode(int e); int getElement(); LinkedNode* getNext(); void setElement(int e); void setNext(LinkedNode *nxt); }; class LinkedStack : public Stack { int stackSize; LinkedNode *head; public: LinkedStack(); int size(); void push(int o); int pop(); int top(); }; #endif #include "LinkedStack.h" /* LinkedNode function * */ LinkedNode::LinkedNode(LinkedNode *nxt, int e) { next = nxt; element = e; } LinkedNode::LinkedNode(int e) : LinkedNode(NULL,e) { } int LinkedNode::getElement() { return element; } LinkedNode* LinkedNode::getNext() { return next; } void LinkedNode::setElement(int e) { element = e; } void LinkedNode::setNext(LinkedNode *nxt) { next = nxt; } /* LinkedStack function * */ LinkedStack::LinkedStack() { stackSize = 0; head = NULL; } int LinkedStack::size() { return stackSize; } void LinkedStack::push(int o) { LinkedNode *node = new LinkedNode(head, o); head = node; stackSize++; } int LinkedStack::pop() { if(size()==0) return -1; LinkedNode *node = head; head = head->getNext(); int ptr = node->getElement(); delete node; stackSize--; return ptr; } int LinkedStack::top() { return head->getElement(); } #include "ArrayStack.h" #include "LinkedStack.h" #define ARRAY_SIZE 10 void invertArray(int array[], int arraySize, Stack &stack) { for(int i=0; i Το Makefile που μεταγλωττίζει τον παραπάνω κώδικα είναι το εξής: StackUsage: ArrayStack.o LinkedStack.o g++ -Wall -g -std=c++11 StackUsage.cpp ArrayStack.o LinkedStack.o -o StackUsage ArrayStack.o: ArrayStack.cpp ArrayStack.h g++ -Wall -g -std=c++11 ArrayStack.cpp -c LinkedStack.o: LinkedStack.cpp LinkedStack.h g++ -Wall -g -std=c++11 LinkedStack.cpp -c clean: rm *.o StackUsage Από τον παραπάνω κώδικα παρατηρούμε ότι η abstract κλάση //Stack// παρέχει μία σειρά από //virtual// μεθόδους οι οποίες υλοποιούνται από τις κλάσεις //ArrayStack// και //LinkedStack//. Η μέθοδος //invertArray// χρησιμοποιεί την abstract κλάση //Stack// ως //interface//. Ανάλογα με το είδος του αντικειμένου τύπου //Stack// με το οποίο θα κληθεί ο παραπάνω κώδικας η εσωτερική υλοποίηση της στοίβας θα είναι διαφορετική. Ο κώδικας όμως που χρησιμοποιεί το //interface// της στοίβας παραμένει αμετάβλητος, ανεξάρτητα από την εσωτερική υλοποίηση. Τα //interfaces// στη C++ υλοποιούνται αποκλειστικά μέσω //abstract// κλάσεων που περιέχουν //pure virtual// συναρτήσεις. Είναι προφανές ότι μία //abstract// κλάση εκτός από //pure virtual// συναρτήσεις μπορεί να περιέχει και //virtual// συναρτήσεις και κανονικές συναρτήσεις, αλλά και μεταβλητές (πεδία). Η παραπάνω παραδοχή "θολώνει" λίγο την έννοια του //interface// στη C++, καθώς επιτρέπει να υπάρχουν δεδομένα και default υλοποιήσεις σε ένα //interface//. Σε κάθε περίπτωση, εάν μία κλάση περιέχει μόνο //pure virtual// συναρτήσεις μπορείτε να θεωρήσετε ότι αντιπροσωπεύει ένα //interface//.