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?
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?
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).
Można zapewnić operatorowi konwersji na placu klasy:
class Square
{
public:
operator int()
{
return side * side;
}
private:
int side;
};
powinien zwracać obszar, a nie stronę. – Dani
Ma wartość true dla bardzo małych instancji kwadratu. –
@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. –
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.
+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
Dzięki za wyszukaną odpowiedź. – Radix
@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