====== 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//.