This is an old revision of the document!
Στη C++ οι μέθοδοι συνηθίζεται να καλούνται συναρτήσεις. Η συγκεκριμένη ονοματολογία προέρχεται ως κληρονομιά από την γλώσσα C. Η βασική διαφορά σε σχέση με την Java είναι ότι μπορείτε να ορίσετε συναρτήσεις οι οποίες δεν ανήκουν σε κλάσεις, όπως παρακάτω.
#include <iostream> using namespace std; int addition (int a, int b) { return a+b; } int main () { int x=5; x = 5 + addition(8,2); cout << "x: " << x << endl; }
Κατά την κλήση μίας συνάρτησης οι παράμετροι της συνάρτησης αντιγράφονται στο stack πριν από την εκτέλεσης της. Μετά την ολοκλήρωση εκτέλεσης οι παράμετροι διαγράφονται από το stack και οποιαδηποτε αλλαγές έγιναν στις παραμέτρους κατά τη κλήσης της συνάρτησης είναι αδύνατο να διατηρηθούν μετά την κλήση της
Εάν θέλουμε οι αλλαγές στα ορίσματα της συνάρτησης να διατηρηθούν και μετά την κλήση της θα πρέπει να περάσουμε τις διευθύνσεις των εμπλεκόμενων μεταβλητών και όχι τις μεταβλητές αυτές καθ' αυτές. Σε αυτή την περίπτωση αντιγράφονται οι διευθύνσεις στο stack και όχι οι τιμές. Οι αλλαγές στις τιμές διατηρούνται ακόμη και μετά την έξοδο από τη συνάρτηση. Δείτε το παρακάτω παράδειγμα που αποτυπώνει τις συγκεκριμένες διαφορές.
#include <iostream> using namespace std; int powerOf2(int x) { x = x*x; return x; } int powerOf2Ref(int &x) { x = x*x; return x; } int powerOf2Ptr(int *x) { *x = (*x)*(*x); return *x; } int main() { int a = 5, b; b = powerOf2(a); cout << "a: " << a <<", b: " << b << endl; a = 5; b = powerOf2Ref(a); cout << "a: " << a <<", b: " << b << endl; a = 5; b = powerOf2Ptr(&a); cout << "a: " << a <<", b: " << b << endl; }
Το αποτέλεσμα της εκτέλεσης του παραπάνω προγράμματος έχει ως εξής:
a: 5, b: 25 a: 25, b: 25 a: 25, b: 25
Παρατηρήστε ότι μετά την έξοδο από τις μεθόδους powerOf2Ref και powerOf2Ptr η μεταβλητή a έχει αλλάξει τιμή κάτι που δεν ισχύει μετά την έξοδο από την powerOf2.
Η C++ (όπως και η Java) επιτρέπει δύο συναρτήσεις να έχουν το ίδιο όνομα αλλά διαφορετικό αριθμό ή τύπο παραμέτρων. Αυτό συμβαίνει διότι η συνάρτηση δεν ορίζεται μόνο από το όνομα της, αλλά από το όνομα της σε συνδυασμό με τις τυπικές παραμέτρους που λαμβάνει. Δείτε το προηγούμενο παράδειγμα προσαρμοσμένο, ώστε οι συναρτήσεις να λαμβάνουν το ίδιο όνομα.
#include <iostream> using namespace std; int powerOf2(int &x) { x = x*x; return x; } int powerOf2(int *x) { *x = (*x)*(*x); return *x; } double powerOf2(double *x) { *x = (*x)*(*x); return *x; } int main() { int a = 5, b; double d = 5.0, e; b = powerOf2(a); cout << "a: " << a <<", b: " << b << endl; a = 5; b = powerOf2(&a); cout << "a: " << a <<", b: " << b << endl; e = powerOf2(&d); cout << "d: " << d <<", e: " << e << endl; }
Παρατηρήστε ότι οι συνάρτηση powerOf2 έχει τρεις διαφορετικές εκδόσεις: μία που λαμβάνει αναφορά σε ακέραιο, μία που λαμβάνει δείκτη σε ακέραιο και μία που λαμβάνει δείκτη σε double. Η διάκριση μεταξύ συναρτήσεων με το ίδιο όνομα γίνεται με βάση τη σειρά και τον τύπο των τυπικών παραμέτρων τους.
Όταν θέλουμε να περάσουμε σε μία συνάρτηση μεγάλα αντικείμενα που περιέχουν πολύ πληροφορία είναι προτιμότερο να τα περάσουμε με αναφορά ακόμη και εάν δεν επιθυμούμε οι πιθανές αλλαγές στις τυπικές παραμέτρους να είναι ορατές μετά την κλήση της συνάρτησης. Ο λόγος είναι ότι η κλήση με αναφορά έχει σταθερό κόστος αντιγραφής ισοδύναμο με το μήκος μίας διεύθυνσης μνήμης, ενώ η αντιγραφή ενός μεγάλου αντικειμένου έχει κόστος όσο το μέγεθος του αντικειμένου.
Για βασικούς τύπους δεδομένων η κλήση με αναφορά δεν έχει καμία επίπτωση στην ταχύτητα εκτέλεσης του προγράμματος.