Η κληρονομικότητα των κλάσεων στη γλώσσα προγραμματισμού C++

Η κληρονομικότητα των κλάσεων στη γλώσσα προγραμματισμού C++

Η κληρονομικότητα των κλάσεων στη C++ εκφράζεται με τον ορισμό μίας βασικής κλάσης (base class) που θεωρείται ως κλάση- πατέρας και τουλάχιστον μίας άλλης η οποία θεωρείται ως παράγωγη κλάση της πρώτης και ονομάζεται υποκλάση (subclass). Η υποκλάση κληρονομεί τις ιδιότητες (properties) και τις μεθόδους της βασικής κλάσης (methods), εφόσον έχουν καθοριστεί ως public εμβέλειας στη βασική κλάση.

Η βασική σύνταξη για τον καθορισμό κληρονομικότητας ανάμεσα στις δύο είναι η εξής:

class mySubclass : public myBaseA, public myBaseB, public myBaseC{ ...}

Η υποκλάση δεν έχει πρόσβαση στις μεθόδους και τις ιδιότητες που έχουν οριστεί ως private στη βασική κλάση. Εάν τίθεται θέμα ασφαλείας σχετικά με τις ιδιότητες και μεθόδους της κλάσης- πατέρα, τότε συνίσταται η χρήσης της δεσμευμένης λέξης καθορισμού εμβέλειας “protected” για τη δήλωσή τους.  Ανάλογα καθορισμένες ιδιότητες και μέθοδοι μπορούν πλέον να είναι προσβάσιμες από την παράγωγη κλάση, δηλαδή τα αντικείμενα αυτής, αλλά όχι από άλλες συναρτήσεις.

Η κληρονομικότητα των κλάσεων στη C++: δυνατότητες κληρονομικότητας (με παράδειγμα)

Απλή κληρονομικότητα

Μέσα στην υποκλάση υπάρχει δυνατότητα να καθοριστούν νέες ιδιότητες και μέθοδοι οι οποίες επεκτείνουν ή ακόμα και αντικαθιστούν ιδιότητες και μεθόδους της βασικής κλάσης.  Στο παράδειγμα που ακολουθεί ορίζεται μία βασική κλάση με το όνομα Shape και δύο παράγωγες υποκλάσεις, Rectangle και Triangle. Η κλάση- γονέας περιέχει μόνο properties , ενώ οι υποκλάσεις περιέχουν από ένα κονστράκτορα και μία μέθοδο.

Παράδειγμα:

#include<iostream>
using namespace std;
class Shape { 
  protected: 
     float width;
     float height;
     float area;
};
class Rectangle : public Shape { 
    public:
      Rectangle(float x, float y){ width=x; height=y; }
      float CalculateArea( ){ area= width * height; return (area); }
};
class Triangle : public Shape{ 
    public:
      Triangle(float x, float y){ width=x; height=y; }
      float CalculateArea( ){ area= width * height / 2; return (area);}
};
int main(){
    Rectangle *rec=new Rectangle(2.2,2) ;
    Triangle *tr =new Triangle(2.2,2);
     cout<<"Area of rectangle = "<<rec->CalculateArea( )<<endl;
    cout<<"Area of triangle = "<<tr->CalculateArea( )<<endl;
    return 0;
}

Παρατηρούμε ότι στις υποκλάσεις δε χρειάστηκε να ορίσουμε εκ νέου τα χαρακτηριστικά τους, εφόσον ταιριάζουν με αυτά της κλάσης- γονέα. Υπενθυμίζουμε τη σημασία των δεσμευμένων λέξεων εμβέλειας προκειμένου να χρησιμοποιηθούν τα μέλη της βασικής κλάσης- στο παράδειγμά μας είναι εμβέλειας protected.

Το αποτέλεσμα στην οθόνη είναι το εξής:

Area of rectangle = 4.4

Area of triangle = 2.2

Πολλαπλή κληρονομικότητα

Μια κλάση μπορεί να δηλωθεί με πολλαπλή κληρονομικότητα (multiple inheritance) με τη χρήση της σύνταξης:

class mySubclass : public myBaseA, public myBaseB, public myBaseC{ ...}

Η υποκλάση κληρονομεί τα public properties και methods όλων των βασικών κλάσεων της δήλωσης.

Η κληρονομικότητα των κλάσεων στη C++: virtual και pure μέθοδοι

Virtual (εικονικές) μέθοδοι

Αν σε μια κλάση δηλώσουμε μια συνάρτηση ως virtual τότε οι υποκλάσεις της κλάσης αυτής μπορούν να αντικαταστήσουν τη συνάρτηση με μια που θα ορίσουν αυτές.  Όταν κληθεί η συνάρτηση που έχει αντικατασταθεί από μια υποκλάση μέσω ενός δείκτη της βασικής κλάσης ο οποίος έχει προέλθει από δείκτη κάποιας υποκλάσης τότε θα κληθεί η αντίστοιχη συνάρτηση της υποκλάσης από την οποία έχει προέλθει ο δείκτης.

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

Η δυνατότητα αυτή προάγει τη C++ από γλώσσα που υποστηρίζει τα αντικείμενα σε αντικειμενοστρεφή γλώσσα.

Παράδειγμα:
Έστω ότι στο παραπάνω παράδειγμα θέλουμε να ορίσουμε τη μέθοδο CalculateArea() στη βασική κλάση Shape. Για να μπορέσει η μέθοδος αυτή να δηλωθεί εκ νέου στην υποκλάση Triangle και να μη δημιουργήσει conflict στον κώδικα, θα πρέπει να την ορίσουμε μέσα στην κλάση- γονέα χρησιμοποιώντας τη δεσμευμένη λέξη virtual. Κατά την εκτέλεση του προγράμματος, αναγνωρίζεται και εκτελείται η σωστή έκδοσή της, δηλαδή αυτή που βρίσκεται μέσα στην υποκλάση Triangle.

#include <iostream.h>
using namespace std;
class Shape { protected:

float width;
float height;
float area;

public:

virtual float CalculateArea( ){ cout<<"Calculating area..."<<endl;}
};
class Triangle : public Shape {
public:
Triangle(float x, float y){ width=x; height=y; }
float CalculateArea( ){ area= width * height; return (area); }
};

int main(){
Triangle *tr =new Triangle(2.2,2);
cout<<"Area of triangle = "<<tr->CalculateArea( )<<endl;
return 0;
}

Κατά την εκτέλεση του κώδικα, καλείται η μέθοδος CalculateArea( ) για το αντικείμενο τύπου Triangle , οπότε εκτυπώνεται το εμβαδόν που ζητάμε και όχι το μήνυμα “Calculating area…”.

Το αποτέλεσμα στην οθόνη είναι το εξής:

Area of triangle = 2.2

Pure (θεωρητικές) μέθοδοι

Όταν μια virtual  μέθοδος μιας κλάσης ορίζεται με τη σύνταξη

(μέθοδος)= 0

τότε η συνάρτηση αυτή ονομάζεται pure (θεωρητική) και δεν υλοποιείται στη συγκεκριμένη κλάση, αλλά στις υποκλάσεις αυτής που θα την καλούν.

Παράδειγμα:

class Shape {
public:
virtual float  CalculateArea() = 0;
};

Ουσιαστικά στο παράδειγμα αυτό και δεδομένου ότι έχουμε ορίσει τις υποκλάσεις που αναφέρθηκαν (Rectangle και Triangle), η μέθοδος υπολογισμού εμβαδού δεν υλοποιείται για την κλάση- γονέα Shape, αλλά είναι δηλωμένη ως μοτίβο προκειμένου να αξιοποιηθεί μόνο από αντικείμενα των  παράγωγων κλάσεων ή αντικείμενα της βασικής κλάσης με δείκτη σε παράγωγη.

Ενδεικτικό παράδειγμα για την έννοια και τη χρηστικότητα των αφηρημένων κλάσεων αποτελεί ο σχεδιασμός του πληροφοριακού συστήματος ενός Πανεπιστημίου, όπου μπορεί να οριστεί η αφηρημένη κλάση person ως βασική κλάση για τις υποκλάσεις student, employee και visitor. Αν και δε θα μπορεί να οριστεί μια μεταβλητή για την αφηρημένη κλάση person, αυτή μπορεί να περιέχει ορισμένα βασικά χαρακτηριστικά όπως birth_date και να επιβάλει την υλοποίηση συγκεκριμένων μεθόδων όπως home_page_URL() ορίζοντάς τις ως θεωρητικές.

Απάντηση

Αυτός ο ιστότοπος χρησιμοποιεί το Akismet για να μειώσει τα ανεπιθύμητα σχόλια. Μάθετε πώς υφίστανται επεξεργασία τα δεδομένα των σχολίων σας.