2011-12-10 12 views
8

Tak, miałem egzamin na drugi dzień, a jednym z pytań było coś bardzo podobnego do tego:Przeciążanie static_cast?

Mamy klasy o nazwie Square który posiada zmienną int side. Jak możemy sprawić, by wydrukowano obszar aSquare?

Czy to możliwe?

Odpowiedz

18

Możliwe jest wykonanie tej pracy, ale nie przez przeciążenie static_cast<>(). To zrobić poprzez przeciążenie operatora 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; 

Pamiętaj, że przeciążone typecast operatorów nie częściej niż zwykle, aby zrobić więcej szkody niż pożytku. Umożliwiają wiele bezsensownych, niejawnych operacji rzutowania. Kiedy czytasz poniższy fragment kodu, myślisz, że "dostaniesz obszar s"?

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

Z pewnością nie. To sprawia, że ​​o wiele więcej sensu i jest o wiele bardziej czytelny:

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

Nie wspominając, że zazwyczaj chcesz mieć dostęp do innych informacji o Square, jak GetSide() lub GetApothem() lub GetPerimeter() czy cokolwiek innego. operator int() oczywiście może zwrócić tylko jeden numer int i nie można mieć wielu operator int() s jako członków klasy.

Oto kolejna sytuacja, w której operator int() sprawia, że ​​kod kompiluje ale nie ma sensu w ogóle:

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

Co to oznacza dla Square być większa niż 42? To bzdura, ale z operator int() powyższy kod skompiluje się, ponieważ Shape jest teraz konwertowalny do int, który można porównać do innego int z wartością 4.

Więc nie piszcie takich operatorów. W rzeczywistości, jeśli przeciążasz operatorów typecast, możesz zastanowić się dwa razy nad tym, co robisz. W rzeczywistości jest tylko kilka przypadków, w których przeciążenie operatora typograficznego jest przydatne w nowoczesnym C++ (na przykład the safe bool idiom).

+0

+1: klasa kwadratowa może korzystać z kilku innych metod, np. 'int GetSideLength() const',' int GetPerimeter() const', i ma na celu ujednoznacznienie, że nazwana metoda powinna być użyta w 'GetArea()'. – rwong

+0

Dzięki za wyszukaną odpowiedź. – Radix

+2

@In silico: W języku C++ 11 nie jest już potrzebny bezpieczny idol bool, ponieważ C++ 11 obsługuje słowo kluczowe 'explicit' dla operatorów konwersji. – smerlin

1

Można zapewnić operatorowi konwersji na placu klasy:

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

powinien zwracać obszar, a nie stronę. – Dani

+2

Ma wartość true dla bardzo małych instancji kwadratu. –

+2

@Dani: Myślę, że brakowało ci sensu. Jestem pewien, że OP wie, jak obliczyć obszar. Pytanie poprawnie odpowiedziało, jak uzyskać int od obiektu kwadratowego, który jest techniczną częścią pytania. –

4

Można przeciążać operatora Obsada:

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

Jedynym problemem jest to, że będzie on używany w sposób dorozumiany i oddające nie robi Ma to sens. Nie można też rozróżnić różne rodzaje odlewów (static_cast, c-style, itp)

Jest to preferowany sposób zrobić rzeczy:

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

Jeśli trzeba użyć obsadę użyć C++ 11 funkcja i oznaczyć ją jako explicit. Zapobiega to domyślnym błędom w rzucaniu.