2011-12-10 20 views
8

Così, ho avuto un esame, l'altro giorno, e una delle domande era qualcosa di molto simile a questo:Sovraccarico di static_cast?

Abbiamo una classe chiamata Square che detiene una variabile int side. Come possiamo rendere possibile che cout << static_cast<int>(aSquare) <<endl; stampi l'area di aSquare?

È possibile?

risposta

18

È possibile farlo funzionare, ma non tramite il sovraccarico static_cast<>(). Fate in modo da sovraccaricare l'operatore typecast:

class Square 
{ 
public: 
    Square(int side) : side(side) {} 
    operator int() const { return side * side; } // overloaded typecast operator 
private: 
    int side; 
}; 

// ... 

// Compiler calls Square::operator int() to convert aSquare into an int 
cout << static_cast<int>(aSquare) <<endl; 

attenzione che gli operatori di overload Typecast il più delle volte tendono a fare più male che bene. Rendono possibili molte operazioni di cast implicite senza senso. Quando leggi questo snippet di codice qui sotto, pensi che "a otterrà l'area di s"?

Square aSquare; 
int a = aSquare; // What the heck does this do? 

Io certamente no. Questo rende molto più senso ed è molto più leggibile:

Square aSquare; 
int a = aSquare.GetArea(); 

per non parlare che di solito si vuole essere in grado di accedere alle altre informazioni Square, come GetSide() o GetApothem() o GetPerimeter() o qualsiasi altra cosa. operator int() ovviamente può restituire solo uno int e non è possibile avere più operator int() s come membri di una classe.

Ecco un'altra situazione in cui il operator int() rende il codice che compila ancora ha alcun senso:

Square s; 
if(s > 42) {} // Huh?! 

Che cosa significa per un Square essere superiore a 42? È una sciocchezza, ma con il operator int() il codice sopra verrà compilato come Shape ora è convertibile in uno int che può essere paragonato a un altrocon un valore 4.

Quindi non scrivere operatori typecast del genere. In effetti, se stai sovraccaricando gli operatori di typecast, potresti voler pensare due volte a quello che stai facendo. In realtà ci sono solo alcuni casi in cui l'overload dell'operatore typecast è utile nel moderno C++ (ad esempio the safe bool idiom).

+0

+1: una classe Square potrebbe utilizzare molti altri metodi, ad es. 'int GetSideLength() const',' int GetPerimeter() const', ed è a scopo di disambiguazione che un metodo denominato dovrebbe essere usato per 'GetArea()'. – rwong

+0

Grazie per l'elaborata risposta. – Radix

+2

@In silico: Con C++ 11 l'idioma bool sicuro non è più necessario, poiché C++ 11 supporta la parola chiave 'explicit' per gli operatori di conversione. – smerlin

1

Si potrebbe fornire un operatore di conversione per la classe Square:

class Square 
{ 
public: 
    operator int() 
    { 
     return side * side; 
    } 
private: 
    int side; 
}; 
+0

dovrebbe restituire l'area, non il lato – Dani

+2

Tiene vero per istanze di quadrato molto piccole. –

+2

@Dani: Penso che ti sia mancato il punto. Sono sicuro che l'OP sa come calcolare l'area. La domanda ha risposto correttamente come ottenere un int da oggetto quadrato che è la parte tecnica della domanda. –

4

È possibile sovraccaricare l'operatore di cast:

struct square { 
    operator int() const { 
    return (side * side); 
    } 
    int side; 
}; 

L'unico problema è che verrà utilizzato implicitamente, e la colata doesn Non ha molto senso qui. Non è inoltre possibile distinguere tra i diversi tipi di calchi (static_cast, c-stile, ecc)

Questo è il modo migliore di fare le cose:

struct square { 
    int get_area() const { 
    return (side * side); 
    } 
    int side; 
} 

Se è necessario utilizzare un cast, utilizzare C++ 11 funzione e contrassegnarlo explicit. Questo impedisce errori di cast impliciti.