Κλάσεις και αντικείμενα

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Ορισμός κλάσεων

Μέθοδοι κατασκευής και καταστροφής

Ιδιότητες και μέθοδοι της κλάσης

Συναρτήσεις friend

Σε μια κλάση μπορούν να οριστούν συναρτήσεις με τον προσδιορισμό 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(12);

        display(b);             // Friend function
}

Ο προσδιορισμός const

Συναρτήσεις που δε μεταβάλλουν μέλη της κλάσης καλό είναι να δηλώνονται και να ορίζονται ακολουθούμενες με τον προσδιορισμό 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 που - εξεζητημένα - εκμεταλλεύεται όλα τα στοιχεία που έχουν αναφερθεί:

point.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 double distance(point p1, point p2);     // Display friend function
        friend void display(point &p);  // Display friend function
};

point.cpp

#include "point.h"
#include <iostream.h>
#include <math.h>

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";
}

double
sqr(double x)
{
        return (x * x);
}

double
distance(point p1, point p2)
{
        return (sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y)));
}

void
point::setpos(int sx, int sy)
{
        this->x = sx;
        point::y = sy;
}

int
point::points_used()
{
        return (numpoints);
}

main.cpp

#include <iostream.h>
#include "point.h"

main()
{
        point a(12);
        point b, *c;

        c = new point(55);
        b.setpos(66);

        a.display();            // Member function
        display(b);             // Friend function
        c->display();
        cout << "Distance from a to b = " << distance(a, b) << "\n";
        cout << "points used = " << point::points_used() << "\n";
        delete(c);
        cout << "points used = " << point::points_used() << "\n";
        return (0);
}

Φροντιστηριακή άσκηση

Να υλοποιηθεί σε C++ μια κλάση που να παριστάνει αντικείμενα σε κίνηση με ιδιότητες την αρχική τους θέση και την ταχύτητά τους στους άξονες x και y και τις παρακάτω μεθόδους:
void setipos(double x, double y)
Θέτει την αρχική θέση του αντικειμένου.
void setvelocity(double x, double y)
Θέτει την ταχύτητα x, y του αντικειμένου.
double getxpos(int t)
Επιστρέφει τη θέση x του αντικειμένου κατά τη χρονική στιγμή t.
double getypos(int t)
Επιστρέφει τη θέση y του αντικειμένου κατά τη χρονική στιγμή t.
Με βάση το παραπάνω να υλοποιηθεί πρόγραμμα που
  1. Ζητάει από το χρήστη τον αριθμό των αντικειμένων που θέλει να δημιουργήσει.
  2. Για κάθε ένα από τα αντικείμενα ζητάει από το χρήστη την αρχική του θέση.
  3. Διαρκώς ζητάει από το χρήστη τον αύξοντα αριθμό ενός αντικειμένου, την ταχύτητά του και ένα χρόνο t και εμφανίζει στην οθόνη τη θέση του κατά το χρόνο t.
Σημείωση: η θέση κάθε αντικειμένου υπολογίζεται μόνο με βάση την αρχική του θέση και την ταχύτητά του.

Παράδειγμα:
n=3

A1x=6
A1y=12
A2x=6
A2y=67
A3x=32
A3y=78

A=2
A2 vx=10
A2 vy=10
t=1
A2x=16 A2y=77

A=1
A1 vx=1
A1 vy=1
t=2
A1x=8 A2y=14

...

Ασκήσεις

Άσκηση 2

  1. Να υλοποιηθούν σε C++ οι κλάσεις andgate, orgate, notgate. Οι κλάσεις αυτές θα προσομοιάζουν τις αντίστοιχες λογικές πύλες. Κάθε κλάση να έχει μεθόδους που να θέτουν τις εισόδους (π.χ. seta, setb) και μέθοδο που να επιστρέφει την τιμή της εξόδου (π.χ. getoutput).
  2. Με τη χρήση των παραπάνω κλάσεων (και μόνο) να υλοποιήσετε μια κλάση που να προσομοιάζει έναν ημιαθροιστή. Η κλάση αυτή να έχει μεθόδους που να θέτουν τις δύο εισόδους και μεθόδους που να επιστρέφουν το άθροισμα και το κρατούμενο.
  3. Να γράψετε ένα πρόγραμμα σε C++ που να τυπώνει τους πίνακες αλήθειας για τις παραπάνω κλάσεις.
  4. (Προαιρετικά) Με τη χρήση των παραπάνω κλάσεων να υλοποιήσετε μια κλάση που να προσομοιάζει έναν πλήρη αθροιστή. Η κλάση αυτή πρέπει να έχει μεθόδους που να θέτουν τις δύο εισόδους και το κρατούμενο εισόδου καθώς και μεθόδους που να επιστρέφουν το άθροισμα και το κρατούμενο εξόδου. Με τη χρήση του πλήρη αθροιστή και τους τελεστές bit της C μπορεί να υλοποιηθεί μια κλάση αθροιστή ακεραίων αριθμών (wordadder) με τον παρακάτω τρόπο:
    /*
     * wordadder.h
     *
     * D. Spinellis, February 2000
     */

    class wordadder {
    private:
            unsigned int a, b;                      // Input values
    public:
            void seta(unsigned int v);              // Set input a
            void setb(unsigned int v);              // Set input b
            unsigned int getsum();                  // Return sum
    };

    /*
     * wordadder.cpp
     *
     * D. Spinellis, February 2000
     */

    #include "wordadder.h"
    #include "fulladder.h"

    void
    wordadder::seta(unsigned int v)
    {
            a = v;
    }

    void
    wordadder::setb(unsigned int v)
    {
            b = v;
    }


    unsigned int
    wordadder::getsum()
    {
            fulladder fa[sizeof(unsigned int) * 8];
            unsigned int i, bit;
            unsigned int result = 0;

            fa[0].setcarryin(false);
            for (i = 0, bit = 1; bit; bit <<= 1, i++) {
                    fa[i].seta(a & bit);
                    fa[i].setb(b & bit);
                    if (bit << 1)           // Do carry-over the last bit
                            fa[i + 1].setcarryin(fa[i].getcarryout());
                    if (fa[i].getsum())
                            result |= bit;
            }
            return (result);
    }
    Ο αθροιστής αυτός μπορεί να χρησιμοποιηθεί ως εξής:
            wordadder add;
            int a, b;

            cin >> a;
            cin >> b;
            add.seta(a);
            add.setb(b);
            cout << a << "+" << b << "=" << add.getsum();
    Δοκιμάστε το!