Hello Class

Τύποι μεταβλητών και κλάσεις

Διάφοροι τύποι μεταβλητών που μπορούν άμεσα να χρησιμοποιηθούν στην C++:
char, short, long, int, float, double, bool ,,,
Η γλώσσα παρέχει την δυνατότητα να φτιάξουμε τους δικούς μας τύπους μεταβλητών και να καθορίσουμε την συμπεριφορά τους με τον τρόπο που εμείς θέλουμε. Ο μηχανισμός γιά την δημιουργία δικής μας έμπνευσης τύπων είναι οι κλάσεις. Οι κλάσεις έχουν δύο μέρη: α) τις μεταβλητές τους, β) τις συναρτήσεις τους (member functions), που διαχειρίζονται τις μεταβλητές τους ή/και κάνουν υπολογισμούς που σχετίζονται με την κλάση.

Στην συνέχεια δημιουργώ μιά κλάση που κάνει την δουλεία του προηγουμένου προγράμματος: α) ζητά από τον χρήστη ένα όνομα β) τυπώνει μήνυμα με το όνομα του χρήστη γ) ρωτά γιά τερματισμό του προγράμματος. Μιά τέτοια κλάσση μπορεί να έχει την μορφή:

Hello class

class  Hello
{
private:
   char name[200];
   bool finish;
public:
   Hello() {finish = false;}
   virtual ~Hello(){}
   bool GetFinishValue() {return finish;}
   void GetNameFromUser();
   void PrintMessage();
   void AskFinish();
};

Συστατικά της κλάσης

char name[200]; Η πρώτη μεταβλητή της κλάσης: ένα διάνυσμα 200 χαρακτήρων που θα δέχεται το όνομα του χρήστη
bool finish; Η δεύτερη μεταβλητή: μιά λογική μεταβλητή που θα καθορίζει συνέχεια ή τερματισμό του προγράμματος
Hello() {finish = false;} Ο κύριος κατασκευαστής (constructor) της κλάσης, που κατά την δημιουργία της θέτει την μεταβλητή finish=false, σε πιό πολύπλοκες κλάσεις μπορεί να γίνονται εδώ κάποιες προετοιμασίες γιά την χρήση της κλάσσης.
virtual ~Hello(){} Ο καταστροφέας (destructor) της κλάσης, που εδώ δεν κάνει τίποτε, αλλά σε πιό σύνθετες κλάσεις συνήθως απελευθερώνει μνήμη που χρησιμοποιεί η κλάση.
bool GetFinishValue() {return finish;} Μιά πολύ απλή συνάρτηση που επιστρέφει την τιμή της μεταβλητής finish
void GetNameFromUser(); Μιά συνάρτηση η οποία θα ζητά από τον χρήστη το όνομά του και θα το αποθηκεύει στην μεταβλητή name (κατασκευάζεται το σώμα της παρακάτω)
void PrintMessage(); Μιά συνάρτηση που τυπώνει κάποιο μήνυμα (κατασκευάζεται το σώμα της παρακάτω)
void AskFinish(); Μιά συνάρτηση που ζητά από τον χρήστη αν θα συνεχίσει ή όχι, και ανάλογα με την απάντηση δίδει τιμή στην finish (το σώμα της κατασκευάζεται παρακάτω)

Το παραπάνω μπλοκ αναγνωρίζεται από την C++ σαν ορισμός μιάς κλάσης. Μερικές συναρτήσεις που έχουν μικρό σώμα μπορούν να ορισθούν μέσα στην κλάση. Στις υπόλοιπες το σώμα τους ορίζεται έξω από το μπλόκ ορισμού, όμως με έναν τρόπο που να συνδέει το σώμα με την αντίστοιχη συνάρτηση. Το παραπάνω μπλόκ ονομάζεται interface της κλάσης. Περιέχει όλη την πληροφορία γιά το τι κάνει η συνάρτηση. Το πως το κάνει αυτό που κάνει καθορίζεται από το σώμα των διαφόρων συναρτήσεων οι οποίες συνολικά αποτελούν (με τα σώματά τους) την implementation (υλοποίηση) της κλάσης. Στην συγκεκριμένη περίπτωση η υλοποίηση είναι η εξής:

Υλοποίηση της κλάσης(implementation)

void Hello::GetNameFromUser()
{
   cout << "Write your name:\n" << endl;
   cin >> name ;
}

void Hello::PrintMessage()
{
   cout <<"\n ********* Hello " << name << 
		 " Welcome to C++  ********\n\n" << endl;
}

void Hello::AskFinish()
{
	char  response[10];
	cout << "Finish?...Yes(Y) ... No(N)....\n" << endl;
	cin  >> response ;
	finish = (response[0]=='Y' || response[0]=='y');
}

Βλέπουμε ότι στην υλοποίηση ορίζεται το σώμα των συναρτήσεων (member functions) της κλάσης. Η C++ αναγνωρίζει ότι πρόκειται για μέλη της κλάσης Hello από την προσθήκη του Hello:: μπροστά από κάθε συνάρτηση.

Οργάνωση του κώδικα μιας κλάσης

Όπως είδαμε προηγουμένως, ο κώδικας που ορίζει μιά κλάση χωρίζεται φυσιολογικά σε δύο μπλοκ. Το πρώτο (interface) ορίζει τις ιδιότητες μιάς κλάσης. Αν ο προγραμματιστής επιλέξει κατάλληλα ονόματα γιά τις συναρτήσεις, στο interface φαίνεται TI ακριβώς κάνει η κλάση. Το ΠΩΣ το κάνει φαίνεται στο άλλο μπλόκ, αυτό της implementation. Την εννοιολογική αυτήν διαίρεση ακολουθούν, κατά κανόνα, οι προγραμματιστές γιά να διαιρέσουν τον κώδικα και να τον τοποθετήσουν σε διαφορετικά αρχεία. Το interface της κλάσης τοποθετήται σε ένα αρχείο με την κατάλληξη .h, ενώ η υλοποίηση (implementation) τοποθετήται σε ένα αρχείο με την κατάλληξη .cpp. Στην συγκεκριμένη περίπτωση, γιά την κλάση Hello θα δημιουργούσαμε τα δυο παρακάτω αρχεία:

Interface, δημιουργούμε αρχείο κειμένου με όνομα HelloClass.h το οποίο περιέχει:

#ifndef  HELLOCLASS
#define  HELLOCLASS

class  Hello
{
private:
   char name[200];
   bool finish;
public:
   Hello() {finish = false;}
   virtual ~Hello(){}
   bool GetFinishValue() {return finish;}
   void GetNameFromUser();
   void PrintMessage();
   void AskFinish();
}; 

#endif // HELLOCLASS

Impementation, δημιουργούμε αρχείο κειμένου με όνομα HelloClass.cpp το οποίο περιέχει:

#include <iostream.h>
#include <HelloClass.h>

void Hello::GetNameFromUser()
{
   cout << "Write your name:\n" << endl;
   cin >> name ;
}

void Hello::PrintMessage()
{
   cout <<"\n ********* Hello " << name << 
		 " Welcome to C++  ********\n\n" << endl;
}

void Hello::AskFinish()
{
	char  response[10];
	cout << "Finish?...Yes(Y) ... No(N)....\n" << endl;
	cin  >> response ;
	finish = (response[0]=='Y' || response[0]=='y');
}

Παλιό πρόγραμμα (Hello) με κλάσεις

Σ΄ένα αρχείο με όνομα Hello.cpp γράφω τον κώδικα:
#include <stdio.h>
#include "HelloClass.h"

int main(int argc, char* argv[])
{
  Hello  h;
  while(h.GetFinishValue()==false)
  {
     h.GetNameFromUser();
     h.PrintMessage();
     h.AskFinish();
  }
  return 0;
}

Ανάλυση του κώδικα

#include <stdio.h> Εντολή συμπερίληψης βασικής βιβλιοθήκης της C++
#include "HelloClass.h" Εντολή συμπερίληψης του αρχείου interface της κλάσης που θα χρησιμοποιήσω
Hello h; Ορισμός μιάς μεταβλητής (h) τύπου Hello. Η h λέγεται και στιγμιότυπο (instance) της κλάσης Hello. Σημείωσε ότι αμέσως μετά τον ορισμό ο compiler εκτελεί τον κατασκευαστή (constructor), σύμφωνα με τον οποίο (δες πιο πάνω) η τιμή της finish ορίζεται false.
while(h.GetFinishValue()==false) Μιά σύνθετη εντολή. Η εντολή while στέκεται στην κεφαλή του βρόγχου και εξετάζει την τιμή της μεταβλητής finish της κλάσης. Την τιμή αυτή την παίρνουμε με την συνάρτηση h.GetFinishValue() και την συγκρίνουμε με την false. Ο βρόγχος συνεχίζει να λειτουργεί εφ΄όσον η τιμή της finish είναι false.
h.GetNameFromUser(); Η συνάρτηση που παίρνει από τον χρήστη το όνομα και το αποθηκεύει στην μεταβλητή name
h.PrintMessage(); Η συνάρτηση που τυπώνει ένα μήνυμα και το όνομα που έδωσε ο χρήστης
h.AskFinish(); Η συνάρτηση που ζητά από τον χρήστη αν θα συνεχίσει ή όχι, και ανάλογα με την απάντηση δίδει τιμή στην finish
Η τελεία h. Καθορίζει ότι οι συναρτήσεις που χρησιμοποιούμε είναι μέλη (member-functions) της κλάσης στην οποία ανήκει η μεταβλητή h

Εκτέλεση του προγράμματος