User Tools

Site Tools


cpp:casting

This is an old revision of the document!


C++ casting

Η C++ εισάγει μια βασική αλλαγή στη φιλοσοφία διαχείρισης των μετατροπών τύπων δεδομένων σε σχέση με τη γλώσσα C. Οι τελεστές casting αποτελούν χαρακτηριστικό παράδειγμα αυτής της αλλαγής. Στη C το “παραδοσιακό” cast — με τη γνώριμη σύνταξη (type)value — λειτουργεί ως ένας μηχανισμός που εξαναγκάζει τη μετατροπή δεδομένων χωρίς ουσιαστικούς περιορισμούς. Αντίθετα, η C++ εισάγει μια οικογένεια τεσσάρων εξειδικευμένων τελεστών (static_cast, dynamic_cast, const_cast, και reinterpret_cast). Οι τελεστές αυτοί βελτιώνουν την αναγνωσιμότητα και επιπλέον (α) επιβάλλουν αυστηρότερο έλεγχο από τον compiler, (β) υποχρεώνουν στον προγραμματιστή να δηλώσει με σαφήνεια την πρόθεσή του, (γ) επιτρέπουν ασφαλείς μετατροπές κατά τη μεταγλώττιση ή (δ) διενεργούν ελέγχους πολυμορφισμού κατά την εκτέλεση του προγράμματος. Παρακάτω αναλύσουμε κάθε ένα ξεχωριστά

static_cast<>

Ο συγκεκριμένος τελεστής μετατροπής τύπου δηλώνει ότι η αλλαγή του τύπου γίνεται κατά τη μεταγλώττιση. Ο compiler ελέγχει ότι η μετατροπή είναι τουλάχιστον θεωρητικά εφικτή.

Παράδειγμα 1ο: Αριθμητικές Μετατροπές και Ακρίβεια

Παρακάτω δίνουμε ένα παράδειγμα μετατροπής τύπου από int σε double για τον υπολογισμό μέσου όρου. Η μετατροπή από ένα βασικό τύπο σε ένα άλλο μπορεί να γίνει με static_cast εφόσον η μετατροπή είναι εφικτή.

#include <iostream>
 
int main() {
    int total_points = 45;
    int total_items = 10;
 
    // Πρόβλημα: Η διαίρεση ακεραίων θα δώσει 4 (χάνεται το .5)
    double average_bad = total_points / total_items; 
 
    // Λύση: Μετατρέπουμε τον έναν ακέραιο σε double πριν τη διαίρεση
    double average_good = static_cast<double>(total_points) / total_items;
 
    std::cout << "Bad Average: " << average_bad << std::endl;  // Εκτυπώνει 4
    std::cout << "Good Average: " << average_good << std::endl; // Εκτυπώνει 4.5
 
    // Μετατροπή από double σε int (explicit truncation)
    double pi = 3.14159;
    int truncated_pi = static_cast<int>(pi); 
 
    std::cout << "Truncated Pi: " << truncated_pi << std::endl; // Εκτυπώνει 3
 
    return 0;
}

Παράδειγμα 2ο: Κληρονομικότητα (Upcasting & Downcasting)

Το static_cast επιτρέπει τη μετακίνηση στην ιεραρχία των κλάσεων, αλλά χωρίς έλεγχο ασφαλείας. Ο compiler υπακούει στην εντολή του προγραμματιστή και επιβάλλει την αλλαγή του τύπου κατά τη μεταγλώττιση. Παρακάτω δίνουμε δύο μετατροπές τύπου μεταξύ κλάσεων που διατηρούν σχέση κληρονομικότητας. Στην πρώτη περίπτωση, η μετατροπή από τη γονική στην απόγονο κλάση επιτρέπει στο πρόγραμμα να λειτουργεί απροβλημάτιστα. Στην δεύτερη περίπτωση η μετατροπή είναι λανθασμένη και το πρόγραμμα τερματίζει αναπάντεχα με SEGMENTATION FAULT.

#include <iostream>
#include <vector>
 
class Base {
public:
    virtual void info() { 
        std::cout << "Είμαι η Base" << std::endl; 
    }
    virtual ~Base() {} // Πάντα virtual destructor στη βασική κλάση
};
 
class Derived : public Base {
private:
    int array[10000];
public:
    void info() override { 
        std::cout << "Είμαι η Derived" << std::endl; 
    }
    void special_function() {
        array[9999] = 1;
        std::cout << "Ειδική λειτουργία της Derived!" << std::endl; 
    }
};
 
int main() {
    Derived* d = new Derived();
 
    // 1. Upcasting: Από Derived* σε Base* (Πάντα ασφαλές)
    // Γίνεται και αυτόματα, το static_cast το κάνει explicit.
    Base* b = static_cast<Base*>(d);
    b->info(); 
 
    // 2. Downcasting: Από Base* σε Derived*
    // Εδώ το static_cast εμπιστεύεται τον προγραμματιστή.
    // Αν το 'b' όντως δείχνει σε Derived, όλα καλά. Αν όχι, θα υπήρχε πρόβλημα
    Derived* d2 = static_cast<Derived*>(b);
    d2->special_function();
 
    Base* real_base = new Base();
    // Ο compiler επιτρέψει τη μετατροπη Base* -> Derived*. 
    // H d3 θα δείχνει σε αντικείμεν τύπου Base
    Derived* d3 = static_cast<Derived*>(real_base); 
 
    d3->special_function(); // ΚΙΝΔΥΝΟΣ: Runtime Crash
 
    delete d;
    delete real_base;
    return 0;
}

dynamic_cast<>

const_cast<>

reinterpret_cast<>

cpp/casting.1777031174.txt.gz · Last modified: 2026/04/24 11:46 by gthanos