Εργαστήριο Τεχνολογίας Λογισμικού
+1 vote
604 views

Μερικές ερωτήσεις επί των διαλέξεων (αλλά και εκτός):

  1. Η global μεταβλητή είναι όταν δηλώνεται εκτός της συνάρτησης ή της κλάσης αλλά εντός της main ή όταν δηλώνεται εκτός τελείως της main;

  2. Ποια είναι η ουσιαστική διαφορά μεταξύ συνάρτησης και μεθόδου (λόγου χάριν μεθόδου κλάσης); Είναι μόνο ότι η πρώτη επιστρέφει τιμή ενώ η δεύτερη όχι;

  3. Τι ακριβώς είναι η μέθοδος δόμησης και αποδόμησης και πού πρακτικά χρειάζονται αυτές μέσα στον κώδικα; Δηλαδή σε τι εξυπηρετούν;

  4. Μπορούμε λίγο να ξεκαθαρίσουμε τη διαφορά μεταξύ των:

     return;  
     return (0);
     return (μεταβλητή ή παράσταση);
    
in progintro by (820 points)
edited by | 604 views

2 Answers

+1 vote

Edit by nickie: Τα περί μεθόδων και κλάσεων στις απαντήσεις (2) και (3) αναφέρονται σε ύλη που θα διδαχθεί στο τέλος του εξαμήνου και στο μάθημα του δευτέρου εξαμήνου.


1) Οι global μεταβλητές δηλώνονται εκτός της main() (και εκτός οποιασδήποτε συνάρτησης ή κλάσης), και είναι ορατές από ολόκληρο το πρόγραμμα.

2) Αν με τη μέθοδο εννοείς διαδικασία, τότε πράγματι η διαφορά είναι ότι αυτή (που είναι μια συνάρτηση τύπου void) δεν επιστρέφει κάποια τιμή, ενώ οι υπόλοιπες συναρτήσεις επιστρέφουν. Αν πάλι αναφέρεσαι σε μεθόδους κλάσης, αυτές είναι οι συναρτήσεις (void ή μη) που ανήκουν σε μια κλάση.

3) Όταν ορίζεις μία κλάση σε ένα πρόγραμμα είναι αναγκαίο να οριστούν και οι constructors και destructors (μέθοδοι δόμησης και αποδόμησης). Ο πρώτος αποτελεί μέθοδο κλάσης ο οποίος καλείται αυτόματα κατά τη δήλωση αντικειμένου αυτής της κλάσης, και δημιουργεί το εν λόγω αντικείμενο. Όταν σταματήσει να χρησιμοποιείται αυτό το αντικείμενο, πρέπει να κληθεί ο destructor προκειμένου να το διαγράψει, αποδεσμεύοντας τη σχετική μνήμη (αν δε γίνει αυτό σωστά μπορεί να προκύψουν προβλήματα όπως κάποιο memory leak, γιατί αντικείμενα που δε χρησιμοποιούνται θα συνεχίζουν να καταλαμβάνουν μνήμη).

4) Η return; χρησιμοποιείται σε συναρτήσεις τύπου void, όπου δεν επιστρέφετααι κάποια τιμή. Η return x; επιστρέφει την τιμή x σε μία συνάρτηση. Η return 0; μπορεί να επιστρέφει την τιμή 0 σε μια συνάρτηση, όμως γράφεται και στο τέλος της main() (στη C++ προστίθεται και αυτόματα από τον μεταγλωττιστή). Τότε πρόκειται για τον κωδικό εξόδου του προγράμματος, που όταν είναι 0 σημαίνει βασικά "ΟΚ, το πρόγραμμα τερματίστηκε επιτυχώς!"

by (380 points)
edited by
0

Ευχαριστώ για την απάντηση. Οπότε:

  1. Η global δεν είναι απαραίτητα εκτός main(). Μπορεί να οριστεί και εντός main(), στην αρχή της, στο κύριο πρόγραμμα όταν καλούμε τις κλάσεις και τις συναρτήσεις και φυσικά έχουν ισχύ σε όλο το πρόγραμμα, σωστά;

  2. Αναφερόμουν στη δεύτερη περίπτωση όπου δεν είχα ξεκαθαρίσει την έννοια μέθοδο. Ευχαριστώ!

  3. Κατάλαβα, ευχαριστώ για την απάντηση!

  4. Σχεδόν κατάλαβα, και θα καταλάβω πλήρως μετά από αυτή την ερώτηση εδώ:
    Έστω έχω την κλάση rectangle:

     class rectangle {
       float plevra_a=a;
       float plevra_b=b;
     public:
       string xroma;
       void set_ab (float a, float b);
     } rect1, rect2; 
    

    Τα παραπάνω αντικείμενα rect1 και rect2 δημιουργούνται αφού έχω συμπεριλάβει τη μέθοδο δόμησης και μόνο; Αλλιώς, και που τα δηλώνω, δεν πρόκειται να δημιουργηθούν; Επίσης, η μέθοδος δόμησης (εδώ με παραμέτρους) ορίζεται εκτός της κλάσης ως π.χ.

     rectangle::rectangle (float a, float b) {
       ...
     }
    

    Σωστά;

0

1. Λάθος! Ξαναδιάβασε τι γράφει η απάντηση!

0

4. Η ύπαρξη ή όχι του κατασκευαστή (μεθόδου δόμησης) επηρεάζει το τι θα εκτελεστεί όταν δημιουργηθούν τα αντικείμενα, όχι το αν θα δημιουργηθούν. Δε χρειάζεται και δεν μπορούμε να πούμε περισσότερα στα σχόλια μιας ερώτησης. Θα μιλήσουμε για κατασκευαστές στο τέλος του εξαμήνου και σε όλο το επόμενο. Μέχρι τότε, ξέχασέ τους...

0 votes

Απαντώ στις νέες απορίες που διατυπώνονται στο σχόλιο.

1) Όπως είπε και ο @vanourogeros οι global μεταβλητές δηλώνονται εκτός της main().

4) Ο constructor πρέπει να έχει δηλωθεί στον ορισμό της κλάσης. Εφόσον τον δηλώσεις, στο παράδειγμα που αναφέρεις θα κληθεί o constructor για τα rect1, rect2.

by (2.9k points)
+1

@AndreasS σε ευχαριστώ για την απάντηση.

  1. Οκ κατάλαβα ευχαριστώ

  2. Ευχαριστώ. Το γνωρίζω αυτό με τη δήλωση απλά αυτό που ρωτώ ουσιαστικά είναι ποια είναι η συγκεκριμένη δουλειά - λειτουργία του constructor; Θέτει τις τιμές στα αντικείμενα κλάσης που έχουν οριστεί στην κλάση;

Ευχαριστώ και πάλι

+1

Για να σε βοηθήσω πρέπει να κάνεις ένα βήμα πίσω και να σκεφτείς "τι είναι μια κλάση?"

Λόγω απλότητας έστω οτι η σωστή απάντηση είναι "ένας τύπος μεταβλητής που δημιουργώ". Δηλαδή αν φτιάξω ένα class Human τότε απο εκεί και έπειτα είμαι σε θέση να δημιουργώ μεταβλητές τύπου Human.
(πχ έστω Human me = new Human();).

Στο παραπάνω παράδειγμα αυτό που βλέπεις να κάνω κατά τη δημιουργία του me(στα δεξία του '=') είναι η κλήση στον constructor.

Οπότε αν έπρεπε να απαντήσω μόνο στην ερώτηση "Τι ρόλο παίζει ο constructor?" θα σου έλεγα (συνοπτικά) τα εξής:

Είναι μια συνάρτηση που ορίζεις για να εκφράσεις το "τι συμβαίνει κάθε φορά που δημιουργείται ένας Human". Στο παραπάνω παράδειγμα η συνάρτηση αυτή του κατασκευαστή πιθανώς δεν έκανε και πολλά. Όμως σκέψου πως θα μπορούσες να περνάς παραμέτρους σε έναν κατασκευαστή (όπως και σε κάθε άλλη συνάρτηση)... πχ

Human me = new Human(firstname, lastname, birthdate)

σε αυτή τη περίπτωση ο κατασκευαστής μάλλον εσωτερικά θα είχε την ευθύνη του να αναθέσει στις εσωτερικές μεταβλητές του Human τις τιμές που πέρασα, έτσι ώστε μετά από αυτή τη γραμμή να μπορώ ελεύθερα να κάνω
cout << me.lastName << endl;
και να τυπωνεται ότι πέρασα τη στιγμή της κατασκευής!
(spoiler: ειναι επισης καλή πρακτική να μην επιτρέπεις απευθείας πρόσβαση στα μέλη της κλάσης σου, αν σου κινει την περιεργια κάνε ένα νέο ποστ για αυτό :) )

Για να είμαι ειλικρινής, ο κατασκευαστής δεν κάνει κάτι που δεν μπορείς να κάνεις κάπως αλλιώς. Θα μπορούσες σε όλη σου τη ζωή να γράφεις κενούς κατασκευαστές και μετά απο κάθε δημιουργία ενός αντικειμένου να έκανες
me.setFirstName("Bobbie");
me.setLastName("Tables");
me.setBirthday(1942);

Ελπίζω να είδες τον χαμένο χρόνο/κόπο του να το γράφεις αυτό συνέχεια :P

In a nutshell : Ο κατασκευαστής περιέχει τα απαραίτητα βήματα (ορισμένα από εσένα) για να θεωρήσεις ένα νέο αντικείμενο έτοιμο προς χρήση.

Μπορεί στα παραδείγματα/ασκήσεις που κάνεις να μην φαίνεται πολύ καθαρά η χρησιμότητα/"ανάγκη" του κατασκευαστή. Σε πιο προχωρημένα concept αντικειμενοστραφούς C++ το να είσαι σε θέση να ορίσεις με ποιά βήματα γίνονται διάφορες λειτουργίες μιας κλάσης (έστω ο κατασκευαστής Human(...) η καποια μέθοδος getFirstname()) αποδευκνύεται αρκετά δυσκολότερο, και ταυτόχρονα σωτήριο.

Αλλά η όλη φιλοσοφία είναι πως το ορίζεις σωστά μία φορά, και το χρησιμοποιείς για πάντα :)

+1

Κατάλαβα. Έγινε ευχαριστώ πολύ για όλα. Θα επιστρέψω με νέες ερωτήσεις σε νέο ποστ :)

301 questions

289 answers

288 comments

903 users