User Tools

Site Tools


cpp:inheritance

This is an old revision of the document!


Κληρονομικότητα

Σε αναλογία με τη Java, οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, αλλά έχουν την δυνατότητα να προσθέσουν και επιπλέον χαρακτηριστικά στη νέα κλάση.

Στο παρακάτω παράδειγμα, από την κλάση Shape2D (διδιάστατο σχήμα) προκύπτει η κλάση Rectangle (ορθογώνιο παραλληλόγραμμο). Η κλάση Shape2D ορίζει την private μεταβλητή color που αφορά το χρώμα του τετραγώνου και το οποίο αποθηκεύεται σε μορφή RGB και την protected μεταβλητή borderWidth που αφορά το πάχος του πλαισίου γύρο από το σχήμα.

Shape2D.cpp
#include <iostream>
#include <string>
using namespace std;
 
#ifndef __SHAPE2D__
#define __SHAPE2D__
 
class Shape2D {
    unsigned int color;
  protected:
    unsigned char borderWidth;
  public:
    Shape2D(unsigned int c, unsigned char bw);
    Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw);
    void setColor(unsigned int c);
    void setColor(unsigned char red, unsigned char blue, unsigned char green);
    unsigned int getColor();
    unsigned char getBorderWidth();
    void setBorderWidth(unsigned char bw);
    unsigned int getArea();
};
 
void Shape2D::setColor(unsigned int c) { color = c; }
void Shape2D::setColor(unsigned char red, unsigned char blue, unsigned char green) {
  color = red;
  color <<= 8;
  color |= blue;
  color <<= 8;
  color |= green;
}
 
unsigned int Shape2D::getColor() {
  return color;
}
 
Shape2D::Shape2D(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {}
Shape2D::Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) {
  setColor(red, blue, green);
}
 
unsigned int Shape2D::getArea() {
  return 0;
}
 
unsigned char Shape2D::getBorderWidth() { return borderWidth; }
void Shape2D::setBorderWidth(unsigned char bw) { borderWidth = bw; }
 
#endif
Rectangle.cpp
#include <iostream>
using namespace std;
 
#include "Shape2D.cpp"
 
class Rectangle : public Shape2D {
  private:
    unsigned int width, height;  
  public:
    Rectangle(unsigned int c, unsigned char bw, unsigned int w, unsigned int h);
    void setWidth(unsigned int w);
    void setHeight(unsigned int h);
    unsigned int getWidth();
    unsigned int getHeight();
    unsigned char getBorderWidth();
    void setBorderWidth(unsigned char bw);
    unsigned int getArea();
};
 
Rectangle::Rectangle(unsigned int c, unsigned char bw, unsigned int w, unsigned int h) : 
  Shape2D(c, bw) , width(w), height(h) { }
 
void Rectangle::setWidth(unsigned int w) { width = w; }
void Rectangle::setHeight(unsigned int h) { height = h; }
unsigned int Rectangle::getWidth() { return width; }
unsigned int Rectangle::getHeight() { return height; }
 
unsigned char Rectangle::getBorderWidth() { return borderWidth; }
void Rectangle::setBorderWidth(unsigned char bw) { borderWidth = bw; }
 
unsigned int Rectangle::getArea() {
  return Shape2D::getArea() + width * height;
}
ShapeUsage.cpp
#include "Rectangle.cpp"
 
int main() {
  Rectangle rectangle(0xffffff, 2, 10, 20);
 
  cout << "[Rectangle Properties] ";
  cout << " color: 0x" << hex << rectangle.getColor() << dec;
  cout << " borderWidth: " << (int)rectangle.getBorderWidth();
  cout << " area: " << rectangle.getArea() << endl;
 
  return 0;
}

Από τα παραπάνω παρατηρούμε τα εξής:

  1. Η κληρονομικότητα δηλώνεται μέσω της δήλωσης class derived_class_name : public base_class_name { }; (στο παραπάνω παράδειγμα class Rectangle: public Shape2D { };).
  2. Η απόγονος κλάση μπορεί να ορίσει επιπλέον πεδία και επιπλέον μεθόδους. Η απόγονος κλάση Rectangle ορίζει τα επιπλέον πεδία width, height και τις επιπλέον μεθόδους getWidth, getHeight, setWidth, setHeight.
  3. Η απόγονος κλάση μπορεί να επαναορίσει μία μέθοδο η οποία είναι ήδη ορισμένη στη γονική κλάση. Η απόγονος κλάση Rectangle επαναορίζει τις μεθόδους setBorderWidth και getBorderWidth.
  4. Τα μέλη της γονικής κλάσης Shape2D που είναι δηλωμένα ως protected είναι προσβάσιμα από την απόγονο κλάση. Στο παραπάνω παράδειγμα η απόγονος κλάση Rectangle έχει πρόσβαση στο protected πεδίο borderWidth της γονικής κλάης.
  5. Τα μέλη της γονικής κλάσης Shape2D που είναι δηλωμένα ως private δεν είναι προσβάσιμα από την απόγονο κλάση Rectangle.
  6. Όπως και στη Java, τα μέλη της γονικής κλάσης Rectangle ή της απογόνου κλάσης Square που είναι δηλωμένα ως public είναι προσβάσιμα από οποιαδήποτε κλάση ή μέθοδο. Για παράδειγμα η public μεθόδος getColor της κλάσης Shape2D είναι προσβάσιμη από οποιοδήποτε κλάση ή μέθοδο (στο παράδειγμα από τη μέθοδο main).

Συνοπτικά ο πίνακας προσβασιμότητας παρατίθεται παρακάτω:

μέλη της γονικής κλάσης
προσβασιμότητα public protected private
μέλη της ίδιας κλάσης ναι ναι ναι
μέλη υποκλάσης ναι ναι όχι
μη μέλη της κλάσης ναι όχι όχι

Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο signature (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να χρησιμοποιήσουμε τη γονική μέθοδο προκειμένου να την επεκτείνουμε. Ο τρόπος χρήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στη μέθοδο το όνομα της γονικής κλάσης. Από το παραπάνω παράδειγμα, δείτε την υλοποίηση της συνάρτησης getArea στην κλάση Rectangle η οποία χρησιμοποιεί την συνάρτηση getArea της γονικής κλάσης Shape2D.

unsigned int Rectangle::getArea() {
  return Shape2D::getArea() + width * height;
}
cpp/inheritance.1493112108.txt.gz · Last modified: 2017/04/25 08:21 (external edit)