Сегодня я пришла на собеседование и мне задали этот интересный вопрос.
Помимо утечки памяти и отсутствия виртуального dtor, почему этот код дает сбой?
#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 **
он указывает на массив прямоугольников. Тогда доступ должен был быть shape [i] -> draw ();->
Была ошибка , сделанная редактором.Ответы:
Вы не можете так индексировать. Вы выделили массив
Rectangles
и сохранили указатель на первый вshapes
. Когда вы этоshapes[1]
делаете, вы разыменовываете(shapes + 1)
. Это даст вам не указатель на следующийRectangle
, а указатель на то, что будет следующимShape
в предполагаемом массивеShape
. Конечно, это неопределенное поведение. В вашем случае вам повезло и вы попали в аварию.Использование указателя на
Rectangle
обеспечивает правильную работу индексации.Если вы хотите иметь
Shape
в массиве разные типы s и использовать их полиморфно, вам понадобится массив указателей на Shape.источник
Как сказал Мартиньо Фернандес, индексация неправильная. Если вы хотите вместо этого сохранить массив Shapes, вам придется сделать это, используя массив Shape *, например:
Обратите внимание, что вам нужно выполнить дополнительный шаг по инициализации Rectangle, поскольку инициализация массива устанавливает только указатели, а не сами объекты.
источник
При индексировании указателя компилятор добавит соответствующую сумму в зависимости от размера того, что находится внутри массива. Скажем, sizeof (Shape) = 4 (так как у него нет переменных-членов). Но sizeof (Rectangle) = 12 (точные числа, скорее всего, неверны).
Итак, когда вы индексируете, начиная, скажем, ... 0x0 для первого элемента, тогда, когда вы пытаетесь получить доступ к 10-му элементу, вы пытаетесь перейти к недопустимому адресу или местоположению, которое не является началом объекта.
источник