====== Κληρονομικότητα ======
Οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, αλλά έχουν την δυνατότητα να προσθέσουν και επιπλέον χαρακτηριστικά στη νέα κλάση.
Στο παρακάτω παράδειγμα, από την κλάση //Shape// (διδιάστατο σχήμα) προκύπτει η κλάση //Rectangle// (ορθογώνιο παραλληλόγραμμο). Η κλάση //Shape// ορίζει την //private// μεταβλητή //color// που αφορά το χρώμα του σχήματος, το οποίο αποθηκεύεται σε μορφή [[wp>RGB]] και την //protected// μεταβλητή //borderWidth// που αφορά το πάχος του πλαισίου γύρο από το σχήμα.
class Shape {
    unsigned int color;
  protected:
    unsigned char borderWidth;
  public:
    Shape(unsigned int c, unsigned char bw);
    Shape(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 int getArea();
};
#include 
using namespace std;
#include "Shape.hpp"
void Shape::setColor(unsigned int c) { color = c; }
void Shape::setColor(unsigned char red, unsigned char blue, unsigned char green) {
  color = red;
  color <<= 8;
  color |= blue;
  color <<= 8;
  color |= green;
}
unsigned int Shape::getColor() {
  return color;
}
Shape::Shape(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {
}
Shape::Shape(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) {
  setColor(red, blue, green);
}
unsigned int Shape::getArea() {
  return 0;
}
#include "Shape.hpp"
class Rectangle : public Shape {
  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 int getArea();
    
    unsigned char getBorderWidth();
    void setBorderWidth(unsigned char bw);
};
#include 
using namespace std;
#include "Rectangle.hpp"
Rectangle::Rectangle(unsigned int c, unsigned char bw, unsigned int w, unsigned int h) : 
  Shape(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 int Rectangle::getArea() {
  /* this is how you call a function 
   * from the parent class.
   */
  int area = Shape::getArea();
  return Shape::getArea() + width * height;
}
unsigned char Rectangle::getBorderWidth() { return borderWidth; }
void Rectangle::setBorderWidth(unsigned char bw) { borderWidth = bw; }
#include "Rectangle.hpp"
#include 
using namespace std;
int main() {
  Rectangle rectangle(0xffffff, 2, 10, 20);
  rectangle.setBorderWidth(8);
  
  cout << "[Rectangle Properties] ";
  cout << " color: 0x" << std::hex << rectangle.getColor() << dec;
  cout << " borderWidth: " << (int)rectangle.getBorderWidth();
  cout << " area: " << rectangle.getArea() << endl;
  
  return 0;
}
Από τα παραπάνω παρατηρούμε τα εξής:
  - Η κληρονομικότητα δηλώνεται μέσω της δήλωσης ''class derived_class_name : public base_class_name { /*...*/ };'' (στο παραπάνω παράδειγμα ''class Rectangle: public Shape { };'').
  - Η απόγονος κλάση μπορεί να ορίσει επιπλέον πεδία και επιπλέον μεθόδους. Η απόγονος κλάση //Rectangle// ορίζει τα επιπλέον πεδία //width, height// και τις επιπλέον μεθόδους //getWidth//, //getHeight//, //setWidth//, //setHeight//.
  - Η απόγονος κλάση μπορεί να επαναορίσει μία μέθοδο η οποία είναι ήδη ορισμένη στη γονική κλάση. Η απόγονος κλάση //Rectangle// επαναορίζει τη μέθοδο //getArea//.
  - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //protected// είναι προσβάσιμα από την απόγονο κλάση. Στο παραπάνω παράδειγμα η απόγονος κλάση //Rectangle// έχει πρόσβαση στο //protected// πεδίο //borderWidth// της γονικής κλάσης. 
  - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //private// δεν είναι προσβάσιμα από την απόγονο κλάση //Rectangle//.
  - Όπως και στη Java, τα μέλη της γονικής κλάσης //Shape// ή της απογόνου κλάσης //Rectangle// που είναι δηλωμένα ως //public// είναι προσβάσιμα από οποιαδήποτε κλάση ή μέθοδο. Για παράδειγμα η //public// μεθόδος //getColor// της κλάσης //Shape// είναι προσβάσιμη από οποιοδήποτε κλάση ή μέθοδο (στο παράδειγμα από τη μέθοδο main).
Συνοπτικά ο πίνακας προσβασιμότητας παρατίθεται παρακάτω:
^                  ^  μέλη της γονικής κλάσης  ^^^
^  προσβασιμότητα  ^  public  ^  protected  ^  private  ^
| από μεθόδους της ίδιας κλάσης  |  ναι  |  ναι  |  ναι  |
| από μεθόδους μίας υποκλάσης  |  ναι  |  ναι  |  όχι   |
| από μία άλλη κλάση χωρίς σχέση κληρονομικότητας  |  ναι  |  όχι  |  όχι  |
===== Κλήση μιας επανα-ορισμένης μεθόδου της γονικής κλάσης από την υποκλάση =====
Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο //signature// (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να καλέσουμε τη μέθοδο της γονικής κλάσης στην απόγονο κλάση προκειμένου να την επεκτείνουμε. Ο τρόπος κλήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στο όνομα της μεθόδου το όνομα της γονικής κλάσης. Από το παραπάνω παράδειγμα, δείτε την υλοποίηση της συνάρτησης //getArea// στην κλάση //Rectangle// η οποία χρησιμοποιεί την συνάρτηση //getArea// της γονικής κλάσης //Shape//.
unsigned int Rectangle::getArea() {
  return Shape::getArea() + width * height;
}