Dr.Paneas

Object Oriented Side of C++

Recommended Posts

Τα παρακάτω tutorial γράφτηκε απο μένα το καλοκαίρι καθώς μελετούσα Αντικειμενοστρεφή προγραμματισμό με την C++. Δεν ειναι για αρχάριους στην C++ αλλά για αρκετά έμπειρους προγραμματιστές με την C++ και το δομημένο τμήμα της. Πάμε λοιπόν:

Γραμμένο απο εμένα. Οι κώδικες εχουν γινει compile με g++ . Καλή ανάγνωση.

1 . Classes

2. Coding Styles

3. Object (instances)

4. Public & Private members

5. Contructor & Destructor

6. Inheritance

-------Overloading Constructors

-------Overriding

-------Hiding & Bypass Hiding

-------Virtual Methods

------- Access to Hidden Virtual Methods

-------- Dynamic Binding

7. Multiple Inheritance - Polymorphism

--------Virtual Classes

--------- Abstract Classes

--------- Pure Functions

8. Static: Methods / Functions / Members

9. Pointer to Function

Link to comment
Share on other sites

Α ν τ ι κ ε ι μ ε ν ο σ τ ρ ε φ η ς ##

################## π ρ ο γ ρ α μ μ α τ ι σ μ ο ς ##

#################################### σ ε γ λ ω σ σ α C + + ##

##

Καποια βασικά για να πιάσετε την ιδέα:

κλασσική αναλογία για να κατανοήσετε τον OOp είναι αυτή με το αμάξι.

Υποθέστε λοιπόν ότι οδηγάτε το αυτοκίνητο σας και θέλετε να πάτε πιο γρήγορα. Γι αυτό πατάτε περισσότερο το

γκάζι. Τόσο απλό.

Τι πρέπει να προηγηθεί όμως πριν μπορέσετε να το κάνετε αυτό ;

1) Πρέπει να κατασκευαστεί το αυτοκίνητο.

2) Για να κατασκευαστεί το αυτοκίνητο πρέπει να υπάρχουν μηχανολογικά σχέδια αυτού.

3) Αυτά τα σχέδια, περιλαμβάνουν τα σχέδια για το γκάζι, το φρένο, το τιμόνι κλπ κλπ.

Κατά μία έννοια λοιπόν, το πετάλι για το γκάζι/φρενο κλπ, στην ουσία "κρύβει" τον μηχανισμό της επιτάχυνσης

του αυτοκινήτου. Ετσι, όλος ο κόσμος ξέρει να οδηγάει πολύ εύκολα, χωρίς να γνωρίζει πως λειτουργεί ένα

αυτοκίνητο.

Αυτός ο μηχανισμός γίνεται μέσω μιας function. Η function περιέχει όλα αυτά τα σχέδια της επιτάχυνσης ώστε oταν πατάμε το πετάλι του γκάζι, το αυτοκίνητο να επιταχύνει. Υπάρχει επίσης μια άλλη function, η οποία περιέχει τον μηχανισμό για να σταματάει το αμάξι όταν πετάμε φρένο. Ακόμα, υπάρχει κι άλλη function που περιέχει τον μηχανισμό για να στρίβουμε το αμάξι με το τιμόνι. Όλες αυτές οι functions περιέχουν του μηχανισμούς για λειτουργίες του αυτοκινήτου.

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

Class, λοιπόν, είναι μια συλλογή - ένα σπίτι - που στεγάζει αυτές τις functions, σαν το σπίτι του μηχανικου που έχει στο γραφείο του

τα σχέδια του νέου μοντέλου αμαξιού της εταιρίας. Σε μία class μπορείς να έχεις μέσα της, 1 ή και περισσότερες member function. Όλες τους

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

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

το αυτοκίνητο στη ζωγραφιά-σχέδιο. Πρέπει λοιπόν, κάποιος, να κατασκευάσει ένα πραγματικό αυτοκίνητο. Να περάσει από το χαρτί στην

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

(δηλαδή ένα Object της Class). Φυσικά μπορούμε να φτιάξουμε 1 και περισσότερα αυτοκίνητα από ένα σχέδιο - άρα μπορούμε να φτιάξουμε ένα ή

και περισσότερα Objects από μια Class. Η Class - δηλαδή τα μηχανολογικά σχέδια του αυτοκινήτου - περιέχουν τους μηχανισμούς

(member functions) οι οποίεις θα υλοποιηθούν με την σειρά τους στο αυτοκίνητο που θα κατασκευάσουμε (δηλαδή το Object).Όταν

πατάτε το γκάζι, τότε στην ουσία καλείται μία λειτουργία του αυτοκινήτου : την επιτάχυνση. Ανάλογα, στην C++, στέλνετε μυνήματα στο

Object (αυτοκίνητο)για να επιταχύνει. Αυτή η διαδικασία της "κλήσης" ενός μηχανισμού/ μιας λειτουργίας(member function) της

Class(μηχανολογικα σχέδια αυτοκινήτου) για να υλοποιηθεί από το Object(αυτοκίνητο) λέται member-function call ή αλλιώς Object Service Request. Κάθε

αυτοκίνητο όμως, έχει το δικό του χρώμα, το δικό το σαλόνι, το δικό του max ταχύτητας, ξεχωριστή δεξαμενή καυσιμων κλπ. Μπορεί να είναι

αυτοκίνητο που προέρχεται από το ίδιο μηχανολογικό σχέδιο. Toyota Auris θα βρείς σε πολλά μοντέλα. Όλα όμως προέρχονται από το ίδιο

σχέδιο. Είναι απλώς διαφορετικά μοντέλα. Σε τι διαφέρουν δηλαδή ; Στις ιδιότητες (attributes). Αρα κάθε object που μπορεί να προέρχεται από

μια Class μπορεί να διαφοροποιείται από ένα Object που προέρχεται από την ίδια Class, γιατί θα έχει διαφορετικά attributes (πχ διαφορετικό

χρωμα). Προσέξτε όμως, οι ιδιότητες (attributes) ΔΕΝ ΕΙΝΑΙ μέρος του μηχανολογικού σχεδιού (δηλαδή της Class) αλλά είναι μέρος που

στεγάζεται στο Object καθ' αυτό. Εν ολίγης, function (member function) : Ο μηχανισμός που υλοποιεί τις διάφορες λειτουργίες

ενός προγράμματος. Το "πώς" της υλοποιεί, παραμένει "κρυφό" μέσα στην function και δεν σας ενδιαφέρει. Class είναι μια συλλογή απο

πληροφορίες - λειτουργίες - μηχανισμούς, που "κρύβονται" μέσα στις member functions (δηλαδή functions που είναι μέλη της Class). Object

είναι αντίτυπο (instance) - υλοποίηση της Class. πχ ενα αυτοκίνητο που έχει μονο γκάζι. πχ ένα αλλό που έχει και γκαζι και φρένο. Attributes είναι οι ιδιότητες του κάθε αντικειμένου ξεχωριστά (πχ το χρώμα του).

Link to comment
Share on other sites

## 0x01 --Classes ##

#############

Είναι μία συλλογή από ιδιότητες. Φανταστείτε κάτι σαν τα σχέδια ενός μηχανικού.

Απλά να ξέρετε ότι είναι μία συλλογή από ιδιότητες, τίποτα παραπάνω για την ώρα.

Εύκολος ορισμός ε ;

Κάθε class έχει 2 πράγματα: Μεταβλητές και Συναρτήσεις (Variables & Functions)

Οι variables(μεταβλητές) που βρίσκονται μέσα σε μία class έχουν ένα ειδικό όνομα.

Λέγονται: Member Variables ή Data Members.

Οι Συναρτήσεις( functions) που βρίσκονται μέσα σε μία class έχουν κι αυτές ένα ειδικό όνομα

Λέγονται: Member Functions ή Methods.

############################################################

Παράδειγμα: πχ έστω ότι έχουμε μια class Gatoula()

Αυτή πιθανόν να περιέχει τα εξής:

Member Variables: int ilikia, char xroma, char ratsa, char xroma_mation, klp klp

Member Functions: void Niaourisma(), void Upnos(), void Perpatima() , void Kunigi_Pontikion() klp klp

Παράδειγμα μιας class ακολλουθεί ακριβως παρακάτω ::::

                                

class Gatoula                                                                                
{                                                                                        
      unsigned int IlikiaTis;                                                                        
      unsigned int VarosTis;                                                                    
      void Niaou();                                                                            
};

Link to comment
Share on other sites

##

## 0x02 --Ονοματολογία και στιλ ##

######################

Κάθε προγραμματιστής έχει υιοθετήσει ένα δικό του coding style. Ετσι και εδώ θα πρέπει να

κατασταλάξετε στην ονομασία των Data Members και των Functions. Διαλέξτε ένα στιλ:

[1] . itsAge

[2] . myAge

[3] . m_Age (το m από την λέξη member)

[4] . mAge

Link to comment
Share on other sites

##

## 0x03 --Object ##

#############

Εχοντας ήδη φτιάξει μια Class με το ονομα Gatoula, τώρα θα φτιάξουμε μία πραγματική γάτα.

Παράδειγμα δήλωσης αντικειμένου

 Gatoula Lucifer     //defines an object Lucifer        

###############################################################

O Lucifer είναι πλέον ένα αντικείμενο τύπου Gatoula, δηλαδή, περιέχει όλες τις ιδιότητες

(μην ξεχνας ότι η class είναι μία συλλογή πληροφοριών) της Class που προέρχεται.

μπορεί να νιαουρίσει, πχ Lucifer.Niaou();

δώστου μια ηλικία, πχ Lucifer.IlikiaTis = 5;

###############################################################

Όταν φτιάχνεις μια class σκέψου ότι φτιάχνεις τον κόσμο. Για να φτιάξεις μία γάτα στο πρόγραμμα σου

πρέπει να τις δώσεις τα χαρακτηριστικά που έχει στον πραγματικό κόσμο. Δηλαδή να της δώσεις

όνομα, χρώμα, ράτσα, πόδια, ουρά, μάτια, μύτι, αυτιά κλπ . Μετά να τις δώσεις αυτά που μπορεί να κάνει

δηλαδή να περπατάει, να κοιμαται, να τρώει, να νιαουρίζει, να κυνηγάει ποντίκια, να πηδάει ψηλά

να εχει 7 ζωές (λεμε τώρα) κλπ. Η class είναι οι οδηγίες για να φτιάξεις πολλές γάτες στ ο προγραμμα

σου. Οι οντότητες που θα πάρουν σάρκα και οστά μέσω των οδηγιών της class είναι το αντικείμενο.

Το αντικείμενο χρησιμοποιεί τις ιδιότητες και τα χαρακτηριστικά μιας class. Οπότε μπορείς να φτιάξεις

διάφορα αντικείμενα/διάφορες γάτες δίνοντας τιμές στις ιδιοτήτες μιας Class. Πχ ο ένας γάτος θα

έχει ηλικία 3, ο άλλος 4, και ο άλλος 3. Αλλά ο τελευταίος θα έχει μαύρο χρώμα, ενώ ο πρώτος θα έχει

καφέ. Επίσης ο μεσαίος γάτος θα μπορεί να κυνηγάει ποντίκια, αλλό οι άλλοι δύο όχι. Όλα αυτά έχουν να

να κάνουν με μία class που έχεις ορίσει την γάτα στο πρόγραμμα σου. Στα αντικείμενα αυτής, δίνεις

τις ιδιότητες της

Link to comment
Share on other sites

## 0x04 --Public & Private members

########################

Εξορισμού, όλα τα members της class είναι private.

Ας δούμε ένα παράδειγμα με public :

/* Example
#include <iostream>
using namespace std;

class Cat        // Defining Class me to onoma Cat
{
   public:    // public access
       int myAge;                //member var
       int myWeight;    //member var
};    // <--------- min ksexaseis to erotimatiko sto telos tis Class

int main()
{
   Cat Kastrato;        define a Object of the Class
   Kastrato.myAge = 5;    // O Kastrato einai pleon 5 xronon
   cout << "O Kastrato einai " << Kastrato.myAge << " xronon" << endl;
   return 0;
}

#####################################################################

## Αν αφαιρέσω την λέξη public, τότε δεν μπορώ μες την main να γράψω Kastrato.myAge = 5;

Ας δούμε ένα παράδειγμα με Private (πιο ασφαλές).

Για να αλλάξω τιμή στα private members θα πρέπει να φτιάξω public methods που να έχουν

πρόσβαση σε αυτά. Αυτές τις ονομάζουμε accessors (access = πρόσβαση)

                                                                                                

#include <iostream>
using namespace std;

class Cat
{
   public:
       int GetAge() const { return myAge; }    // accessor function inline
       void SetAge( int age) { myAge = age; }    // accessor function inline
       void Niaou();        // public method
   private:
       int myAge;        // private data member;
};

int main()
{
   Cat Arpiah;
   Arpiah.SetAge(5);
   cout << "I Ilikia tis Arpiah einai : " << Arpiah.GetAge() << endl;
   return 0;
}

Link to comment
Share on other sites

##

## 0x05 --Constructor / Destructor ##

########################

Κάθε αντικείμενο έχει εναν Constructor και εναν Destructor (υπάρχει και ο Copy Constructor αλλα δεν θα σχολιασω τιποτα γι δ'αυτον).

Αυτά είναι κάτι σαν την προεπιλεγμένη τιμή που παίρνει το αντικείμενο με το που δημιουργείται. Ειναι τι θελουμε να γινετε οταν δημιουργειται και οταν καταστρέφεται.

πχ Εστω οτι θέλουμε εξορισμού, ο γάτος μας να είναι 9 χρονών με το που τον αρχικοποιουμε:

#include <iostream>
using namespace std;

class Gatos
{
   public:
       Gatos ( int arxiki_ilikia) { myAge = arxiki_ilikia; }        // Constructor; i allios Gatos() { myAge = 9 ; } i allios Gato(): myAge(9) {}
       ~Gatos() {}        // Destructor - den kanei tipota
       int getAge() const { return myAge; }    // accessor function
       int setAge( int age ) { myAge = age ; }    // accessor function
   private:
       int myAge;
};

int main()
{
   Gatos Garfield(9);
   cout << "O Garfield einai " << Garfield.getAge() << " xronon " << endl;
   Garfield.setAge(5);
   cout << "Tora omos einai : " << Garfield.getAge() << " xronon " << endl;
   return 0;
}

Link to comment
Share on other sites

##

## 0x06 --Inheritance ##

###############

Εχουμε τα θηλαστικα. Αυτα κοιμουνται και τρωνε. Ο Σκυλος ειναι θηλαστικο. Ο Σκυλος γαβγιζει.

[Ο Σκυλος ειναι θηλαστικο. Ο Σκυλος τρωει, κοιμαται και γαβιζει. Το πιασες ;

Ορισμός --->

Class DerivedClass : accessType BasedClass
Παράδειγμα:

                                            

#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       Thilastiko(): itsAge(0) {}
       ~Thilastiko() {}
       int GetAge() const { return itsAge; }
       void SetAge(int age) { itsAge = age; }
       void Sleep()  const { cout << "Shhhh. I am sleeping\n"; }
   protected:
       int itsAge;
};

class Skylos : public Thilastiko
{
   public:
       void Bark() const { cout << "Gav Gav Gav!!!\n"; }
};

int main()
{
   Skylos Rudolf;
   cout << "O Rudolf einai : " << Rudolf.GetAge() << " xronon " << endl;
   Rudolf.SetAge(3);
   cout << "O Rudolf einai : " << Rudolf.GetAge() << " xronon " << endl;
   Rudolf.Bark();
   return 0;
}

Overloading Constructors

Παράδειγμα

#include <iostream>
using namespace std;

class HeavyMetalBand
{
   public:
       HeavyMetalBand(){} // Constructor
       HeavyMetalBand( int members ):itsMembers(members) {}  // i allios meta to (int members) { itsMembers = members; }
       ~HeavyMetalBand() {}    // Destructor

       // Accessors
       int GetMembers() const { return itsMembers; }
       void SetMembers( int mMembers ) { itsMembers = mMembers; }

       // Other Methods
       void PlayMusic() const { cout << "...Keep on rocking in the free world...\n"; }

   protected:
       int itsMembers;
};

class LeadGuitar : public HeavyMetalBand
{
   public:
       // Constructors & Overloaded Constructors
       LeadGuitar() {}
       LeadGuitar(int yearsOfExperience ) { itsYearsExp = yearsOfExperience;} // A Tropos me =
       LeadGuitar(int yearsOfExperience, int Age):itsYearsExp(yearsOfExperience), itsAge(Age) {} // B Tropos me :
       LeadGuitar(int Age, int Guitars, int SongsComposed):itsAge(Age), itsGuitars(Guitars), itsSongs(SongsComposed) {}
       ~LeadGuitar() {}

       //Accessors
       int GetExp() const { return itsYearsExp; }
       int GetAge() const { return itsAge; }
       int GetNumOfGuitars() const { return itsGuitars; }
       int HowManySongs() const { return itsSongs; }

       void SetExp( int mYears ) {itsYearsExp = mYears;}    // Den yparxei o B Tropos
       void SetAge( int mAge ) { itsAge = mAge; }        // kathos edo exoume Methods (Member Function)
       void SetGuitars ( int mGuitars ) { itsGuitars = mGuitars; }    // kai oxi  constructors kai destructors
       void SetSongs( int mSongs) { itsSongs = mSongs; }    // o A Tropos paizei mono me Constructors kai Destructors

       // Other Methods
       void RiffEmAll() const { cout << "Metal up your ass! Treat me, baby ... \n"; }

   private:
       int itsYearsExp, itsAge, itsGuitars, itsSongs;
};

int main()
{
   HeavyMetalBand Metallica(4);
   cout << "Metallica is consisted of " << Metallica.GetMembers() << " members " << endl;    

   LeadGuitar KirkHammet;
   LeadGuitar DaveMustaine(17,32);
   LeadGuitar JamesHetfield(17,11,52);    //He is Rythm Guitar anyway...
   // cout whatever ... I am boring 4 typing so long... You got the point, don't ya ?
   return 0;
}

#####################################################################

Overriding & Hiding & Calling Base Methods

Overriding:

Εχω μια method στην base class Thilastiki με το ονομα Speak() { cout << "To thilastiko milaei" }

και μετα φτιαχνω μια derived class Skylos και θελω να βαλω κι εδω μια method Speak()

υπάρχει όμως ήδη απο πριν αλλα εγω θελω ο σκυλος να κανει Γαβ Γαβ και οχι να λεει: "Το θηλαστικο μιλάει"

ετσι φτιαχνω μια ίδια method, με

[1] --> Ιδιο ή διαφορετικο return type

[2] --> Ιδιο όνομα

[3] --> Ιδια λίστα παραμέτρων

[4] --> Με την λέξη const (αν έγινε η χρηση της στην base class method)

[5] --> Με διαφορετικό implementation ( πχ cout << cout << "Gav Gav Gav" )

#####################################################################

Παράδειγμα: Overriding

class Mammal
{
 public:
   // constructors
   Mammal() {}
   ~Mammal() {}
   //Other methods
   void Speak()const { cout << ?Mammal sound!\n?; }
   void Sleep()const { cout << ?shhh. Iʼm sleeping.\n?; }
};

class Dog : public Mammal
{
 public:
  // Constructors
   Dog(){}
   ~Dog(){}
   // Other methods
   void WagTail() const { cout << ?Tail wagging...\n?; }
   void BegForFood() const { cout << ?Begging for food...\n?; }
   void Speak() const { cout << ?Woof!\n?; }    // Overriding Base Method Speak
};

Hiding:

Αν η base class method Speak έχει διάφορες παραλαγες τις (δηλαδη έχει γίνει overload) πχ Speak(Greek),

ή Speak(int lekseis, int protaseis) και φυσικά υπάρχει και η απλή η Speak(), τότε:

αν κάνω overriding την Speak() , τότε αυτόματα, κρύβω τις παραλαγές τις δεν μπορώ να τις καλέσω από την

derived class.

Παράδειγμα: Hiding ##

class Mammal
{
   public:
   Mammal(){}
   ~Mammal(){}
   void Speak() const { cout << "To thilastiko milise kai eipe tin teleutaia tou leksi" ; }
   void Speak(int words) { cout << "To thilastiko milise kai eipe tis " << words << " teleutaies tou lekseis"; }
};

class Dog: public Mammal
{
   public:
   Dog() {}
   ~Dog() {}
   void Speak() const { cout << "O skylos milise kai eipe tin teleutaia tou leksi"; }
};

int main
{
   Mammal Platupodaros;
   Dog Skylaki;
   Platupodaros.Speak();
   Sylaki.Speak()
   Platupodaros.Speak(5);
   // Skylaki.Speak(5) ----> Θα ειναι ερρορ γιατι έχει γινει hidden

To πιάσατε ; Οποτε υπάρχει ο κανόνας:

Αν κανεις override μια method που εχει γινει overload , τοτε εχει 2 επιλογες:

[1] --> Θα κανει override αυτη που θες και αυτοματα η αλλες θα γινουν hidden

[2] --> Θα τις κανεις ολες αναγκαστικα overriding χωρις να μεινει καμια hidden

#include <iostream>
using namespace std;
class Mammal
{
   public:
   Mammal(){}
   ~Mammal(){}
   void Speak() const { cout << "To thilastiko milise kai eipe tin teleutaia tou leksi\n" ; }
   void Speak(int words) { cout << "To thilastiko milise kai eipe tis " << words << " teleutaies tou lekseis\n"; }
};

class Dog: public Mammal
{
   public:
   Dog() {}
   ~Dog() {}
   void Speak() const { cout << "O skylos milise kai eipe tin teleutaia tou leksi\n"; }

int main()
{
   Mammal Platupodaros;
   Dog Skylaki;
   Platupodaros.Speak();
   Skylaki.Speak();
   Platupodaros.Speak(5);
   Skylaki.Mammal::Speak(5); // Ayto paizei mia xara omos! Xexexexe!
   // Skylaki.Speak(5) ----> Θα ειναι ερρορ γιατι έχει γινει hidden
   return 0;
}

#include <iostream>
using namespace std;
class Mammal
{
   public:
   Mammal(){}
   ~Mammal(){}
   void Speak() const { cout << "To thilastiko milise kai eipe tin teleutaia tou leksi\n" ; }
   void Speak(int words) { cout << "To thilastiko milise kai eipe tis " << words << " teleutaies tou lekseis\n"; }
};

class Dog: public Mammal
{
   public:
   Dog() {}
   ~Dog() {}
   void Speak() const { cout << "O skylos milise kai eipe tin teleutaia tou leksi\n"; }

int main()
{
   Mammal Platupodaros;
   Dog Skylaki;
   Platupodaros.Speak();
   Skylaki.Speak();
   Platupodaros.Speak(5);
   Skylaki.Mammal::Speak(5); // Ayto paizei mia xara omos! Xexexexe!
   // Skylaki.Speak(5) ----> Θα ειναι ερρορ γιατι έχει γινει hidden
   return 0;
}

Bypass the Hiding

Τι γίνετε όμως βαριέστε να κάνετε overriding όλες τις methods (καλό είναι να μην βαριέστε όμως) ;

Πώς θα χρησιμοποιήσετε την method Speak(int words) στο Skylaki ; ; ;

#######################################################################

## Παράδειγμα: bypass the hiding

#include <iostream>
using namespace std;
class Mammal
{
   public:
   Mammal(){}
   ~Mammal(){}
   void Speak() const { cout << "To thilastiko milise kai eipe tin teleutaia tou leksi\n" ; }
   void Speak(int words) { cout << "To thilastiko milise kai eipe tis " << words << " teleutaies tou lekseis\n"; }
};

class Dog: public Mammal
{
   public:
   Dog() {}
   ~Dog() {}
   void Speak() const { cout << "O skylos milise kai eipe tin teleutaia tou leksi\n"; }

int main()
{
   Mammal Platupodaros;
   Dog Skylaki;
   Platupodaros.Speak();
   Skylaki.Speak();
   Platupodaros.Speak(5);
   Skylaki.Mammal::Speak(5); // Ayto paizei mia xara omos! Xexexexe!
   // Skylaki.Speak(5) ----> Θα ειναι ερρορ γιατι έχει γινει hidden
   return 0;
}

########################################################################

##

## Το παραπάνω κόλπο είναι : derived_class.base_class::base_method(parameter)

## Προσοχή όταν κάνετε overriding να μην ξεχνάτε την λέξη const αν υπάρχει [\b]

##########################################################################

Virtual Methods (How deep is the rabbit's hole)

Ξέρουμε ότι ο Σκύλος κληρονομεί τις ιδιότητες (data & methods) των θηλαστικών. Λογικό και κατανοητό.

Η C++ όμως παρέχει και το εξής: pointer τύπου δεδομένων base class που κρατάει ως τιμή την διεύθυνση μνήμης

της derived class. Δηλαδή pointer τύπου Θηλαστικού, που κρατάει την διεύθυνση του Σκύλου. Τωρα θα πείτε: Ε (;;;

Δηλαδή:

Thilastiko *ptr = new Skylos // ενώ μέχρι τώρα γράφαμε : Skylos ptr;
Τι κάνει ^^^ : Φτιάχνει ένα αντικείμενο Skylos, και έναν pointer που δέχεται τιμές τύπου Thilastiko.

Ο Σκύλος όμως είναι θηλαστικό, άρα είμαστε μια χαρά! (αφού class Skylos : public Thilastiko )

Αλλάζει επίσης και ο τρόπος που καλούμε methods.

Παλιά (που λεει ο λογος) :

ptr.method();
Τώρα :
ptr -> method();
Πιο είναι το πρόβλημα όμως ; Αν κάνεις overriding μια method, τότε αντί να καλέσει την method απο την derived class

θα καλέσει την hidden method της base class. Δες το ακόλουθω παράδειγμα:

##Example - Παλιος Τρόπος############################################################

                                        

#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       void Speak() { cout << "Thilastiko milaei" << endl; }
};

class Skylos : public Thilastiko
{
   public:
       void Speak()    { cout << "Woof Woof Woof" << endl;}
};

int main()
{
   Skylos Beetoven;
   Beetoven.Speak();
   return 0;
}

###########################################################################

## Output: Woof Woof Woof

###########################################################################

Example - Καινούριος Τρόπος (δες την διαφορα στο output)                                                            

#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       void Speak() const { cout << "Thilastiko milaei" << endl; }
};

class Skylos : public Thilastiko
{
   public:
       void Speak() const { cout << "Woof Woof Woof" << endl;}
};

int main()
{

   Thilastiko *Beetoven = new Skylos;
   Beetoven -> Speak();    // palia grafame Beetoven.Speak();

   return 0;
}

##########################################################################

## Output: Thilastiko milaei

###########################################################################

Όπως βλέπεις δεν πιάνει το overriding. Αυτό συμβαίνει γιατί ο pointer επειδή είναι τύπου Thilastiko βλέπει όλες τις function

του thilastiko (aka της base class) . Ο τρόπος για να χρησιμοποιήσεις το overriding όπως και πριν είναι ένας:

Να κάνεις την method speak, τύπου virtual. Αυτό είναι, virtual.

Virtual κάνεις όσες methods θέλεις/ξέρεις από πριν να κάνεις overriding

Σωστο παράδειγμα με Virtual Functions

                                                                                
#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       Thilastiko() {}    // constructor
       virtual ~Thilastiko() {}    // Destructor PANTA VIRTUAL
       virtual void Speak() const { cout << "Thilastiko milaei" << endl; }
};

class Skylos : public Thilastiko
{
   public:
       Skylos() {}    // constuctor
       virtual ~Skylos() {}    //destructor PANTA VIRTUAL
       virtual void Speak()    const { cout << "Woof Woof Woof" << endl;}
};

int main()
{

   Thilastiko *Beetoven = new Skylos;
   Beetoven -> Speak();    // palia grafame Beetoven.Speak();

   return 0;
}

##########################################################################

## Output: Woof Woof Woof

##########################################################################

Προσβαση στη hidden virtual base method

Example

#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       Thilastiko() {}    // constructor
       virtual ~Thilastiko() {}    // Destructor PANTA VIRTUAL
       virtual void Speak() const { cout << "Thilastiko milaei" << endl; }
};

class Skylos : public Thilastiko
{
   public:
       Skylos() {}    // constuctor
       virtual ~Skylos() {}    //destructor PANTA VIRTUAL
       virtual void Speak()    const { cout << "Woof Woof Woof" << endl;}
};

int main()
{

   Thilastiko *Beetoven = new Skylos;
   Beetoven -> Speak();    // palia grafame Beetoven.Speak();
   Beetoven->Thilastiko::Speak();    // palia grafame Beetoven.Thilastiko::Speak();

   return 0;
}

#########################################################################

## Output: Woof Woof Woof

## Thilastiko milaei

#########################################################################

Example Dynamic Binding

#include <iostream>
using namespace std;

class Thilastiko
{
   public:
       Thilastiko() {}    // constructor
       virtual ~Thilastiko() {}    // Destructor PANTA VIRTUAL
       virtual void Speak() const { cout << "Thilastiko milaei" << endl; }
};

class Skylos : public Thilastiko
{
   public:
       Skylos() {}    // constuctor
       virtual ~Skylos() {}    //destructor PANTA VIRTUAL
       void Speak()    const { cout << "Woof Woof Woof" << endl;}
};

class Cat : public Thilastiko
{
   public:
       Cat() {}    // constructor
       virtual ~Cat() {}    //Destructor PANTA VIRTUAL
       virtual void Speak() const { cout << "Niaou Niaou Niaou" << endl; }
};

class Horse : public Thilastiko
{
   public:
       Horse() {}    // constructor
       virtual ~Horse() {}    //Destructor PANTA VIRTUAL
       virtual void Speak() const { cout << "Xlimintrisma" << endl; }
};

class Cow : public Thilastiko
{
   public:
       Cow() {}        // constructor
       virtual ~Cow() {}    // Destructor PANTA Virtual
       virtual void Speak() const { cout << "Mooooo Mooooo Mooooo" << endl; }
};

int main()
{

   // Static
   // Thilastiko *ptr = new Skylos;

   // Dynamic Binding Runtime
   //The Reason you learn subclass pointer definition
   //

   Thilastiko  *pinakas[5]; // Pinakas (se periptosi pou den to ksereis, ola ta arrays einai pointers)
                         // pou krataei dedomena typoy Thilastiko
   Thilastiko *ptr;        // pointer tupou Thilastiko , edo 8a grafame Thilastiko *ptr = new Skylos
   int choice, i;
   cout << "Please choose: " << endl;
   for(i=0; i<5; i++)
   {
       cout << " Skylos(1)    Gata(2)       Alogo(3)    Agelada(4) :";
       cin >> choice;
       switch (choice)
       {
           case 1:        ptr = new Skylos;    // to ptr einai idi Thilastiko *ptr
                       break;
           case 2:        ptr = new Cat;    
                       break;
           case 3:        ptr = new Horse;
                       break;
           case 4:        ptr = new Cow;
                       break;
           default:        ptr = new Thilastiko;
                       break;
       }
       pinakas[i] = ptr;
   }
   for(i=0; i<5; i++)
   {
       pinakas[i] -> Speak();
   }

   return 0;
}

Output:

Please choose:

Skylos(1) Gata(2) Alogo(3) Agelada(4) :1

Skylos(1) Gata(2) Alogo(3) Agelada(4) :2

Skylos(1) Gata(2) Alogo(3) Agelada(4) :3

Skylos(1) Gata(2) Alogo(3) Agelada(4) :4

Skylos(1) Gata(2) Alogo(3) Agelada(4) :5

Woof Woof Woof

Niaou Niaou Niaou

Xlimintrisma

Mooooo Mooooo Mooooo

Thilastiko milaei

Σημαντικά πράγματα που πρέπει να ξέρεις για τις virtual functions

Οταν γράφεις: Thilastika *ptr = new Dog;

Tότε φτιάχνετε ένα κουτί μέσα στην μνήμη του υπολογιστή (heap) το οποίο είναι χωρισμένο σε δύο μέρη

το ένα μέρος είναι το 1)Thilastiko Part και το δευτερο μέρος είναι 2)Dog Part. Αυτά τα δύο βρίσκονται μέσα στο κουτί

το οποίο κουτί είναι το αντικείμενο Dog

Όταν κανω virtual μια method της base class Thilastiko πχ την void Speak(), παω την αλλαζω σε virtual void Speak()

τότε το αντικείμενο πρέπει να είναι σε θέση να ακουλοθεί τα ίχνη αυτής της virtual void Speak(). Πώς το πετυχaiνει ;

Αρχικά όπως μάθαμε πιο πανω, καλείται ο Base Constructor (aka Thilastika Constructor)

καλείται αυτός, τότε ο compiler φτιάχνει έναν πίνακα που των χωρίζει σε 2 μέρη (οπως πριν)

αυτός ο πίνακας λέγεται v-table του Thilastika. Τι περιέχει αυτός ο πίνακας όμως ;

Είναι χωρισμένος σε 2 μέρη. Το ένα μέρος του λέγεται 1)Thilastiko και το άλλο λέγεται 2)v-ptr

Το v-ptr είναι ο pointer που δείχνει την virtual method. Δηλαδη κρατάει την διεύθυνση της virtual method (& Speak)

Μετά καλείται ο Derived Constructor (aka Dog Constructor)

και ο compiler κάνει παλι το ίδιο. Φτιάχνει έναν πίνακα που λέγεται v-table του αντικεμενου Dog

Αυτός είναι χωρισμένος σε δυο μέρη. Το 1)Dog και το αλλο 2)v-ptr

To v-ptr δείχνει στην virtual method Speak της Base Class , δηλαδή δείχνει στο &Mammal:Speak ενώ οι άλλες

derived έχουν διεύθυνση &Dog:Move. Προσεχε, το v-ptr δείχνει μόνο στην virtual method void Speak.

#############################################################################

## Κατι ακομα: Αν εχεις μια derived method Move που δεν υπάρχει στην base class τότε δεν μπορεις να την καλεσεις

## με κανεναν τροπο. Τι θα κανεις ; Θα το μαθεις μετα, λεγεται typeCasting.

#############################################################################

Link to comment
Share on other sites

## 0x07 --Multiple Inheritance ##

####################

Εχεις δυο classes: Αλογο και Πτηνό. Θες να φτιαξεις μια τριτη class Πήγασσος. Τι ειναι ομως αυτο ; Πουλί ή Αλογο ;

είναι και απο τα δύο. Γράφεται:

class Pigasos : public Alogo, public Pouli

Παράδειγμα

                                                                                                    
#include <iostream>
using namespace std;

class Alogo
{
   public:
       Alogo() {}        // constructor
       virtual ~Alogo() {}    // destructor

       // Accessors Methods
       // variemai na grafo

       // Other Methods
       virtual void xlimintrisma() const { cout << "Xlimintrizo\n"; }
};

class Pouli
{
   public:
       Pouli() {}        // Constructor
       virtual ~Pouli() {}    // Destructor

       // Accessors
       // variemai na grafo

       // Other Methods
       virtual void petao() const { cout << "Petao\n"; }
};

class Pigasos : public Alogo, public Pouli
{
   public:
       Pigasos() {}        // constructor
       virtual ~Pigasos() {}    // destructor
};

int main()
{
   Alogo * ptrAlogo;
   Pouli * ptrPouli;
   Pigasos * ptrPigasos;
   int choice, i;
   cout << "Please choose:\n";
   cout << "Alogo(1), Pouli(2), Pigasos(3) : ";
   cin >> choice;
   switch (choice)    {
       case 1:        ptrAlogo = new Alogo;
               break;
       case 2:        ptrPouli = new Pouli;
               break;
       case 3:        ptrPigasos = new Pigasos;
               break;
       default:    cout << "Error input. Program terminated. . . .";
               return -1;
               break;
   }

   if (choice == 1)    { ptrAlogo -> xlimintrisma(); }
   if (choice == 2)    { ptrPouli -> petao(); }
   if (choice == 3)    { ptrPigasos -> xlimintrisma(); ptrPigasos -> petao(); }


   return 0;
}

Virtual Classes

Animal

Horse Bird <--- Horse and Bird derived απο την Animal, και μεταξυ τους εχουν ως μωρό τους την Pegasus

Pegasus

Για να εξασφαλίσεις οτι classes προέρχονται από την ίδια κοινή base class, τις κάνω virtual

Αφού ξέρεις από πριν ότι από μια class θα ξεπεταχτούν αρκετές subclasses και όχι απλά μόνο μία, τότε

είναι καλή τακτική να τις κάνεις virtual. ##

Example

#include <iostream>
using namespace std;

enum XROMA { ASPRO, MAVRO, KAFE };

class Zoa        // common base class for both Alogo & Pouli
{
   public:
       Zoa() {}
       Zoa( int age ):itsAge(age) {}
       virtual ~Zoa(){}
       virtual int GetAge() const { return itsAge; }
       virtual void SetAge( int mAge) { itsAge = mAge; }
   protected:
       int itsAge;
};

class Alogo : virtual public Zoa
{
   public:
       Alogo() {}
       Alogo(int age, XROMA color):itsAge(age), itsColor(color)    {}
       virtual ~Alogo()    {}
       virtual int GetAge() const { return itsAge; }
       virtual void SetAge( int mAge )    { itsAge = mAge; }
       virtual XROMA GetColor()  const { return itsColor; }
       virtual void SetColor( XROMA mColor) { itsColor = mColor; }
   protected:
       XROMA itsColor;
       int itsAge;
};

class Pouli : virtual public Zoa
{
   public:
       Pouli() {}
       Pouli(int age, XROMA color): itsColor(color), itsAge(age) {}
       virtual ~Pouli() {}
       virtual int GetAge() const { return itsAge; }
       virtual void SetAge( int mAge) { itsAge = mAge; }
       virtual XROMA GetColor() const { return itsColor; }
       virtual void SetColor( XROMA mColor ) { itsColor = mColor; }
   protected:
       XROMA itsColor;
       int itsAge;
};

class Pigassos : public Alogo, public Pouli
{
   public:
       Pigassos() {}
       Pigassos(int age, XROMA body, XROMA ftera) { body = Alogo::itsColor; ftera = Pouli::itsColor; itsAge = age; }
       virtual ~Pigassos() {}
       virtual int GetAge() const { return itsAge; }
       virtual void SetAge( int mAge) { itsAge = mAge; }
       virtual XROMA GetColorBody() const  { return Alogo::itsColor; }
       virtual void SetColorBody(XROMA mbody) { Alogo::itsColor = mbody; }
       virtual XROMA GetColorFtera() const { return Pouli::itsColor; }
       virtual void SetColorFtera(XROMA mftera) { Pouli::itsColor = mftera; }
   protected:
       int itsAge;
};

int main()
{
   Alogo *pAlogo = new Alogo(2,KAFE);
   Pigassos *pPigas = new Pigassos(12, ASPRO, ASPRO);
   cout    << "O Pigassos exei ilikia " << pPigas -> GetAge()
       << " xroma somatos " << pPigas -> GetColorBody()
       << " xroma fteron " << pPigas -> GetColorFtera() << endl;
   cout << "\nTo alogo exei xroma: " << pAlogo -> GetColor () ;
   pAlogo -> SetColor( MAVRO );
   cout << "\nTo alogo exei xroma: " << pAlogo -> GetColor () ;
   cout << "\nO Pigassos exei xroma somatos: " <<  pPigas -> GetColorBody() << endl;
   return 0;
}

#######################################################################

Abstract Class

Συχνα χρειαζεται να φτιαξετε μια class σαν οδηγο. Δεν προκειται ποτε να φτιαξετε αντικειμενο για αυτη την

αλλά θέλετε να την χρησιμοποιήσετε για να κρατάτε έναν οδηγό/πατούρα των methods

πχ εχω μια class abstract που λεγεται Shape. Απο κει βγαζω 2 derived class Κυκλος και Ορθογωνιο

για τον σχεδιασμό τους και τα γεωμετρικα χαρακτηριστικά χρησιμοποιηώ τις methods του Shape

Πες τώρα ότι θελεις να φτιαξεις μια class Τετραγωνο. Αυτη όμως είναι μια ειδικη περίπτωση του ορθογωνίου

οποότε γιατι να την ξαναγράφεις ; Αρκεί να την περάσεις (μεσω constructor overloading) στο ορθογώνιο

Pure Function: Βάζουμε τις methods της Abstract Class. Μετα απο αυτο ειναι αδυνατο να δημιουργηθεί

αντικείμενο της abstract class.

Παράδειγμα


       // Method to be Override
       virtual void Draw() = 0;    // pure function
       private:
};

//    /    /    /    /    /    /    /    /    /    /    /
// Derived Classes
// ///////////////////////
//1st  Derived Cycle    //
// //////////////////////
class Circle : public Shape    // publicaly access type of Shape
{
   public:
   Circle(int radius):itsRadius(radius) {}        //call -> Circle(5) ,  5=radius
   virtual ~Circle(){}

   // Override Shape Accessors
   virtual long GetArea() { return 3 * itsRadius * itsRadius; } // 3*5*5 = 75
   virtual long GetPerim() { return 6 * itsRadius; }        // 6*5 = 30

   // Override Shape Method Draw
   virtual void Draw();         // 8a grapso meta ti 8a kanei, edo den exo xoro
   private:
   int itsRadius;            // to 5 8a isxuei mono gia autin tin class.
   int itsCircumference;
};

// Implementation of Method Draw of the Circle class
void Circle::Draw()
{
   cout << "Circle drawing routine here!\n";
}

/////////////////////////////////
// 2i Derived Class Rectangle     //
// ///////////////////////////////
class Rectangle : public Shape
{
   public:
       Rectangle(int len, int width):itsLength(len), itsWidth(width) {}    //Rectangle(5,10) 5=length, 10 = width
       virtual ~Rectangle() {}

       // Overriding accessors
       virtual long GetArea() { return itsLength * itsWidth; }    // 5*10 = 50
       virtual long Getperim() { return 2*itsLength + 2*itsWidth; }    // 5*2 + 10 *2 = 30

       // New Methods !!!!!
       virtual int GetLength() { return itsLength; }    // GetLength = 5,  epeidi to 5 den pernaei (private) stin derived square 8a perasei i method
       virtual int GetWidth() { return itsWidth; }    // GetWidth = 10. to 10 den pernaei (private) stin derived square 8a perasei i method

       // Overriding DrawMethod
       virtual void Draw();    // 8a tin anaptikso meta
   private:
       int itsLength;        // epeidi den pernane auta, ( logos einai epeidi einai private)
       int itsWidth;        // 8a peraso tis methods pou kratane autous tous arithmous (giati na min kano protected omos o anomalos ? )
};

// Implementation of Draw  Method (Rectangle Class)
void Rectangle::Draw()    // zografizei ena tetragono me 5 kai 10
{
   for(int i =0; i<itsLength; i++)
   {
       for ( int j =0; j<itsWidth; j++)
       {
           cout << "x";
       }
       cout << endl;
   }
}

// Special Class Square
// Derived from Rectangle which derived from Shape
class Square : public Rectangle
{
   public:
       Square(int len);    // square(5)  5 = lenth
       Square(int len, int width);    // square(5,5) 5=length=width
       ~Square() {}

       // Override accessors
       long GetPerim() { return 4 * GetLength(); } // 4*5 = 20
};
// paratiro oti edo den exo tis class:
// GetArea
// void Draw --> simantiko! Giati arage den tin exo ?

// Implementation of Square Constructor
// Overloading 1
Square::Square(int len):Rectangle(len,len) {}    //trofodoti to len tou square os Length=Width gia tin Rectangle

//Overloading 2
Square::Square(int len, int width):Rectangle(len,width) //trofodototei ta len kai width tou Square sta antistoixa tou Rectangle
{
   if( GetLength() != GetWidth())    // An to Rectangle exei width = length
   {
       cout << "This is not a rectangle\n";
   }
}

int main()
{
   int choice;
   bool fQuit = false;
   Shape *pointer;
   cout << "(1)Circle (2)Rectangle (3)Square (0)Quit: ";
   cin >> choice;
   while(!fQuit) {

       switch(choice){
       case 0: fQuit = true;
               break;
       case 1: pointer = new Circle(5);
                   break;
       case 2: pointer = new Rectangle(4,6);
                   break;
       case 3: pointer= new Square(5);
           break;
       default:
           cout << "Please enter a number [0-3]" << endl;
           break;
       }

       if( !fQuit){
           pointer ->Draw();
           fQuit = true;
       }
       delete pointer;
       pointer = 0;
       cout << endl;


   }
   return 0;
}

Link to comment
Share on other sites

## 0x08 --Static Function / Members ##

#######################

Μερικές φορές θέλεις να έχεις μια μεταβλητή ή μια συνάρτηση (κάτι σαν globe) που να μπορεί να ελέγχει ανα

πάσα στιγμή κάποια δεδομένα που σχετίζονται με αντικείμενα ίδιου τύπου (πχ εχεις 5 γάτες)

Αυτό γίνεται με static functions καθώς μεσω αυτών μπορείς να τις καλέσεις είτε μεσω object είτε μεσω class

Ακολουθεί ένα παράδειγμα όπου οι static functions, χρησιμοποιούν τις static variables. Αν τις τελευταιες τις βαλω

public τότε θα είναι διαθεσιμες σε όλους. Συνηθίζεται να είναι είτε private είτε protected.

Example

#include <iostream>
using namespace std;

class Gata
{
   public:
       Gata() { PosesGates++; }    // constructor
       ~Gata() { PosesGates--; }    // destructor

       // Static Function
       // Accessed through Object or through Class itself
       static int GetPosesGates() { return PosesGates; }
       // ^^^ DEN EINAI POTE const

   private:
       static int PosesGates;
};

// Initialize static
int Gata::PosesGates = 0;

int main()
{

   //Ftiaxno mia Gata Object
   Gata Lougritia;

   //Kalesma static meso Class
   cout << Gata ::GetPosesGates() << endl;

   //kalesma static meso Object
   cout << Lougritia.GetPosesGates() << endl;

   return 0;
}

Link to comment
Share on other sites

## 0x09 --Pointer to Function ##

####################

## Ειναι πολυ χρησιμο για δυναμική επιλογή του χρήστη ποια function θελει να καλέσει

## οποτε φτιαχνεις εναν pointer ο οποιος δειχνει σε μια function με ίδιο return type και παραμέτρους

####################################################################

πχ int pros8esi (int x, int y) { return x + y; } είναι μια function

φτιαχνω εναν pointer στην function : int (* pointer2Function) (int, int)

μετα βαζω τον pointer να δειχνει στην συγκεκριμενη function: pointer2Function = pros8esi

και για να καλεσω την συναρτηση, καλω τον pointer που δειχνει στην συναρτηση: pointer2Function(2,5)

##########################################################################

Παράδειγμα:

#include <iostream>
using namespace std;

void Tetragono (int &x, int &y)
{
   x = x * x;
   y = y * y;
}

void Kubos (int &x, int &y)
{
   int temp;

   temp = x;
   x = x * x;
   x = x * temp;

   temp = y;
   y = y * y;
   y = y * temp;
}

void Swap(int &x, int &y)
{
   int temp;

   temp = x;
   x = y;
   y = temp;
}

void Read(int &TimiEna, int &TimiDuo)
{
   cout << "Dose nea timi Ena: ";
   cin >> TimiEna;
   cout << "Dose nea timi Duo: ";
   cin >> TimiDuo;
}

void Print(int x, int y)
{
   cout << "x: " << x << " y: " << y << endl;
}

int main()
{
   // pointer to function
   // which returns void
   // parameters : int , int
   void (* pFunc) (int &, int &);
   bool fQuit = false;

   int TimiEna = 1, TimiDuo = 2;
   int choice;

   while (!fQuit)
   {
       cout <<" (0)Quit (1)Allagi Timon (2)Tetragono (3) Kubos (4)Swap: ";
       cin >> choice;

       switch(choice)
       {
           case 1: pFunc = Read;
               break;
           case 2: pFunc = Tetragono;
               break;
           case 3: pFunc = Kubos;
               break;
           case 4: pFunc = Swap;
               break;
           default: fQuit = true;
       }

       if(!fQuit)
       {
           Print(TimiEna, TimiDuo); // kalo tin function Print me klisi Timis
           pFunc(TimiEna, TimiDuo); // kalei tin function pou deixnei apo prin meso tou pointer
           Print(TimiEna, TimiDuo);
       }
   }
   return 0;
}

Να σημειωσω οτι ειναι αρκετα επικυνδινο αυτο και πλεον (τουλαχιστον στο Qt) γινεται μεσω SLOTS - METHODS .

Αν θέλετε κι αλλα πείτε μου.

Αν έχετε διορθώσεις πείτε μου.

Αν διαφωνείται με κάτι πείτε μου.

Αν αν αν αν ... στείλτε ενα PM.

Link to comment
Share on other sites

@Dr.Paneas Χωρίς να θέλω να σε θίξω/προσβάλλω και κοιτώντας μόνο να προφυλάξω το hwbox.gr , είσαι σίγουρος πώς τα έχεις γράψει εσύ όλα αυτά? Γιατί στο http://www.linuxformat.gr υπάρχουν ακριβώς τα ίδια γραμμένα, με άλλους τίτλους και απο χρήστη με άλλο όνομα, πολύ πρίν το περσινό καλοκαίρι .

Σε παρακαλώ αμα δεν είναι δικά σου βάλε τα λινκ που πρέπει, άμα είναι δικά σου , my bad :) !

Link to comment
Share on other sites

Ναι Γορίλα εγώ τα έχω γράψει αυτά.

Πιθανά username μου: BlackSlash13, Paneas13, Dr.Paneas, WiludrakeGR, Wiludrake, Druid,Iron_Druid,Master_Prophet, Morphine_Child, PanouleXxX ισως ξεχασα κανενα :P

Καλα κανεις και το λες, γιατι υπάρξα και εγω Admin παλιότερα και ξερω τι παίζει με τις "πηγές". Εχεις τον λόγο μου ότι αν είναι να ποστάρω κάτι που δεν είναι δικό μου θα επισημάνω και τις πηγές και τον συντάκτη.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now