Poszedłem dziś na rozmowę kwalifikacyjną i zadano mi to interesujące pytanie.
Oprócz wycieku pamięci i faktu, że nie ma wirtualnego dtora, dlaczego ten kod się zawiesza?
#include <iostream>
//besides the obvious mem leak, why does this code crash?
class Shape
{
public:
virtual void draw() const = 0;
};
class Circle : public Shape
{
public:
virtual void draw() const { }
int radius;
};
class Rectangle : public Shape
{
public:
virtual void draw() const { }
int height;
int width;
};
int main()
{
Shape * shapes = new Rectangle[10];
for (int i = 0; i < 10; ++i)
shapes[i].draw();
}
Shape **
Wskazuje na tablicę prostokątów. Wtedy dostęp powinien mieć kształty [i] -> draw ();->
był błąd popełniony przez redaktora.Odpowiedzi:
Nie możesz tak indeksować. Przydzieliłeś tablicę
Rectangles
i zapisałeś wskaźnik do pierwszego inshapes
. Kiedy robiszshapes[1]
wyłuskiwanie(shapes + 1)
. To nie da ci wskaźnika do następnegoRectangle
, ale wskaźnik do tego, co będzie następneShape
w przypuszczalnej tablicyShape
. Oczywiście jest to niezdefiniowane zachowanie. W twoim przypadku masz szczęście i masz awarię.Użycie wskaźnika, aby
Rectangle
indeksowanie działało poprawnie.Jeśli chcesz mieć
Shape
w tablicy różne rodzaje znaków i używać ich polimorficznie, potrzebujesz tablicy wskaźników do Shape.źródło
Jak powiedział Martinho Fernandes, indeksowanie jest nieprawidłowe. Jeśli zamiast tego chcesz przechowywać tablicę kształtów, musisz to zrobić za pomocą tablicy Shape *, na przykład:
Zwróć uwagę, że musisz wykonać dodatkowy krok inicjalizacji Rectangle, ponieważ inicjalizacja tablicy ustawia tylko wskaźniki, a nie same obiekty.
źródło
Podczas indeksowania wskaźnika kompilator doda odpowiednią ilość w oparciu o rozmiar tego, co znajduje się w tablicy. Powiedzmy, że sizeof (Shape) = 4 (ponieważ nie ma zmiennych składowych). Ale sizeof (Rectangle) = 12 (dokładne liczby są prawdopodobnie błędne).
Więc kiedy indeksujesz zaczynając od powiedzmy ... 0 x 0 dla pierwszego elementu, wtedy kiedy próbujesz uzyskać dostęp do dziesiątego elementu, próbujesz udać się pod nieprawidłowy adres lub lokalizację, która nie jest początkiem obiektu.
źródło