User Tools

Site Tools


cpp:interfaces

This is an old revision of the document!


Interfaces

Η C++ δεν διαθέτει interfaces με τον αυστηρά ορισμένο τρόπο που αυτά ορίζονται στη Java. Αντ' αυτού υλοποιεί την λειτουργικότητα των interfaces μέσω abstract κλάσεων, δηλαδή κλάσεων που δεν μπορούν να δώσουν αντικείμενα. Στο παράδειγμα που ακολουθεί ορίζουμε το interface Stack το οποίο μπορεί να αποθηκεύει ακεραίους.

Η abstract base class Stack έχει δύο υποκλάσεις την κλάση ArrayStack που υλοποιεί τη στοίβα μέσω ενός πίνακα και την κλάση LinkedStack που υλοποιεί τη στοίβα μέσω απλά συνδεδεμένης λίστας.

Stack.h
#include <iostream>
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
ArrayStack.h
#include <iostream>
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
ArrayStack.cpp
#include "ArrayStack.h"
 
ArrayStack::ArrayStack(int cap) {
  capacity = cap;
  stackSize = 0;
  array = new (nothrow) int[capacity];
}
 
int ArrayStack::size() {
  return stackSize;
}
 
void ArrayStack::push(int o) {
  if(stackSize==capacity) {
    int *_array = new (nothrow) int[2*capacity];
    for(int i=0; i<stackSize; i++)
      _array[i] = array[i];
    delete[] array;
    array = _array;
  }
  array[stackSize++] = o;
}
 
int ArrayStack::pop() {
  return array[--stackSize];
}
 
int ArrayStack::top() {
  return array[stackSize];
}
LinkedStack.h
#include <iostream>
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
LinkedStack.cpp
#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 (nothrow) 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();
}
StackUsage.cpp
#include "ArrayStack.h"
#include "LinkedStack.h"
 
#define ARRAY_SIZE 10
 
void invertArray(int array[], int arraySize, Stack &stack) {
  for(int i=0; i<arraySize; i++)
    stack.push(array[i]);
 
  for(int i=0; i<arraySize; i++)
    array[i] = stack.pop();
}
 
int main() {
 
  //ArrayStack st;
  LinkedStack st;
  int array[] = { 100, 99, 98, 97, 96, 95, 94, 93, 92, 91 };  
 
  for(int e:array)
    cout << e << endl;
  cout << endl;
 
  invertArray(array, ARRAY_SIZE, st);
 
  for(int e:array)
    cout << e << endl;
}

Οι παραπάνω κλάσεις μεταγλωττίζονται ως εξής:

g++ -g -std=c++11 -o stack StackUsage.cpp ArrayStack.cpp LinkedStack.cpp

Από τον παραπάνω κώδικα παρατηρούμε ότι η κλάση 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.

cpp/interfaces.1493194434.txt.gz · Last modified: 2017/04/26 07:13 (external edit)