- Η δήλωση μιας κλάσης (class)
είναι παρόμοια με αυτή μιας δομής:
class point {
int x, y;
};
- Οι κλάσεις χρησιμοποιούνται για την υλοποίηση αφηρημένων τύπων
δεδομένων.
Για το σκοπό αυτό μπορούμε να ορίσουμε μέλη (members)
της κλάσης:
μεταβλητές και συναρτήσεις
που είναι ορατά μόνο από συναρτήσεις που αναφέρονται στον τύπο αυτό
(private) καθώς και μεταβλητές και συναρτήσεις που είναι καθολικά
ορατά (public).
Οι μεταβλητές ορίζουν ιδιότητες (properties)
και οι συναρτήσεις ορίζουν
μεθόδους πρόσβασης (methods)
των αντικειμένων της κλάσης.
Παράδειγμα:
class point {
private:
int x, y;
public:
int getx();
int gety();
void setpos(int sx, int sy);
void display();
};
Στο παραπάνω παράδειγμα τα μέλη (ιδιότητες) της κλάσης x, y δεν είναι ορατά και προσβάσιμα
παρά μόνο από τις συναρτήσεις (μεθόδους) της κλάσης getx, gety, setpos και display.
- Ο ορισμός των συναρτήσεων της κλάσης γίνεται με τη χρήση της
σύνταξης κλάση::συνάρτηση.
Παράδειγμα:
int
point::getx()
{
return (x);
}
int
point::gety()
{
return (y);
}
void
point::display()
{
cout << "(" << x << "," << y << ")\n";
}
void
point::setpos(int sx, int sy)
{
x = sx;
y = sy;
}
- Αφού δηλωθεί μια κλάση (τυπικά σε ένα αρχείο κλάση.h) και οριστούν
οι συναρτήσεις της (τυπικά σε ένα αρχείο κλάση.cpp) μπορούν να οριστούν
μεταβλητές με τον τύπο της κλάσης.
Πρόσβαση στις συναρτήσεις της κλάσης έχουν οι μεταβλητές με τη
σύνταξη μεταβλητή.συνάρτηση.
Παράδειγμα:
#include <iostream.h>
#include "point.h"
main()
{
point a;
point b, *c;
c = new point;
b.setpos(6, 6);
cout << b.getx();
a.display();
b.display();
c->display();
}
- Οι συναρτήσεις της κλάσης μπορούν να έχουν πρόσβαση στα στοιχεία της
κλάσης με τους εξής τρόπους:
- με το όνομά τους (π.χ. x),
- μέσω της ορισμένης από τη γλώσσα
μεταβλητής this που δείχνει στην κλάση (π.χ. this->x),
- με πρόθεμα το όνομα της κλάσης για να αποφεύγεται η σύγχυση
όταν υπάρχει τοπική μεταβλητή με το ίδιο όνομα (π.χ. point::x).
Παράδειγμα:
void
point::setpos(int sx, int sy)
{
this->x = sx;
point::y = sy;
}
- Σε κάθε κλάση μπορεί να οριστεί μια
συνάρτηση κατασκευής (constructor) με όνομα ίδιο
με αυτό της κλάσης και μια
συνάρτηση καταστροφής (destructor) με όνομα το
όνομα της κλάσης με το πρόθεμα ~.
Η συνάρτηση κατασκευής καλείται κάθε φορά που δημιουργείται
ένα νέο αντικείμενο (σε επίπεδο καθολικό, τοπικό, ή με new).
Η συνάρτηση καταστροφής καλείται κάθε φορά που παύει να υπάρχει
ένα αντικείμενο δηλαδή αντίστοιχα όταν τελειώνει το πρόγραμμα, όταν
η ροή βγαίνει από το τοπικό τμήμα, ή καλείται η delete.
Το όρισμα που δηλώνουμε στη συνάρτηση κατασκευής επιτρέπει προσδιορισμό
ιδιοτήτων του αντικειμένου που δημιουργούμε (π.χ. τον αριθμό στοιχείων
σε μια στοίβα) ή αρχικών τιμών.
Η συνάρτηση καταστροφής δε δέχεται κάποιο όρισμα.
Οι συναρτήσεις αυτές μπορούν να χρησιμοποιηθούν για να διαχειριστούν τη
μνήμη αντικειμένων που απαιτούν τη χρήση δυναμικής μνήμης με κατάλληλες
κλήσεις στις new και delete.
Παράδειγμα:
class stack {
private:
int *values;
int size;
int sp;
public:
stack(int size); // Constructor
~stack(); // Destructor
};
stack::stack(int size)
{
stack::size = size;
values = new int[size];
}
stack::~stack()
{
delete[] values;
}
- Η κλήση της συνάρτησης κατασκευής μπορεί να γίνει κατά τον
ορισμό μιας μεταβλητής με τη μορφή "κλάση μεταβλητή = κλάση(όρισμα)" ή
συνοπτικότερα με τη μορφή "κλάση μεταβλητή(όρισμα)".
- Σε μια κλάση μπορούν να δηλωθούν (με τον προσδιορισμό static)
μεταβλητές οι οποίες υπάρχουν μόνο μια φορά για όλη την κλάση,
καθώς και συναρτήσεις που μπορούν
να κληθούν με τη σύνταξη κλάση::συνάρτηση.
Οι μεταβλητές αυτές χρησιμοποιούνται για την επεξεργασία στοιχείων
που αφορούν ολόκληρη την κλάση και όχι τα αντικείμενά της.
Οι συναρτήσεις που έχουν οριστεί static δεν έχουν πρόσβαση σε μη
static μεταβλητές ούτε στη μεταβλητή this.
Η αρχικοποίηση των μεταβλητών που έχουν δηλωθεί static πρέπει να γίνει
σε καθολικό επίπεδο, μια φορά για κάθε κλάση.
Το παρακάτω παράδειγμα ορίζει έναν μετρητή numpoints που μετρά πόσα
σημεία είναι ενεργά καθώς και την αντίστοιχη συνάρτηση πρόσβασης:
class point {
private:
int x, y;
static int numpoints;
public:
// ...
static int points_used();
};
int point::numpoints = 0;
// Constructors
point::point(int sx, int sy)
{
x = sx;
y = sy;
numpoints++;
}
point::point()
{
x = y = 0;
numpoints++;
}
// Destructor
point::~point()
{
numpoints--;
}
// Access function
int
point::points_used()
{
return (numpoints);
}
- Σε μια κλάση μπορούν να οριστούν συναρτήσεις με τον προσδιορισμό
friend.
Οι συναρτήσεις αυτές ορίζονται σε καθολικό επίπεδο και μπορούν να
έχουν πρόσβαση στα στοιχεία private της κλάσης.
Οι συναρτήσεις friend χρησιμοποιούνται όταν η χρήση των συναρτήσεων
μέλους δεν είναι βολική.
Παράδειγμα:
class point {
private:
int x, y;
static int numpoints;
public:
// ...
friend void display(point& p); // Display friend function
};
// Friend function; used as display(a)
void
display(point& p)
{
cout << "(" << p.x << "," << p.y << ")\n";
}
main()
{
point b = point(1, 2);
display(b); // Friend function
}
- Συναρτήσεις που δε μεταβάλλουν μέλη της κλάσης καλό είναι να δηλώνονται
και να ορίζονται ακολουθούμενες με τον προσδιορισμό const:
class point {
private:
int x, y;
public:
int getx() const; // Access functions
int gety() const;
void display(); // Display member function
// ...
};
int
point::getx() const
{
return (x);
}
Ο προσδιορισμός αυτός αναγκάζει το μεταγλωττιστή να ελέγχει αν η δέσμευση
αυτή τηρείται μέσα στο σώμα της συνάρτησης.
- Το παρακάτω παράδειγμα ορίζει και χρησιμοποιεί
την κλάση point που - εξεζητημένα - εκμεταλλεύεται όλα τα στοιχεία που
έχουν αναφερθεί:
#include <iostream.h>
class point {
private:
int x, y;
static int numpoints;
public:
point(); // Default contructor
point(int sx, int sy); // Other constructor
~point(); // Destructor
int getx() const; // Access functions
int gety() const;
void display(); // Display member function
void setpos(int sx, int sy); // Set position
static int points_used(); // Return number of points
friend void display(point& p); // Display friend function
};
int point::numpoints = 0;
point::point(int sx, int sy)
{
x = sx;
y = sy;
numpoints++;
}
point::point()
{
x = y = 0;
numpoints++;
}
point::~point()
{
numpoints--;
}
int
point::getx() const
{
return (x);
}
int
point::gety() const
{
return (y);
}
// Member function; used as a.display();
void
point::display()
{
cout << "(" << x << "," << y << ")\n";
}
// Friend function; used as display(a)
void
display(point& p)
{
cout << "(" << p.x << "," << p.y << ")\n";
}
void
point::setpos(int sx, int sy)
{
this->x = sx;
point::y = sy;
}
int
point::points_used()
{
return (numpoints);
}
main()
{
point a(1, 2);
point b, *c;
c = new point(5, 5);
b.setpos(6, 6);
a.display(); // Member function
display(b); // Friend function
c->display();
cout << "points used = " << point::points_used() << "\n";
delete(c);
cout << "points used = " << point::points_used() << "\n";
}