Fui a uma entrevista de emprego hoje e recebi uma pergunta interessante.
Além do vazamento de memória e do fato de não haver dtor virtual, por que esse código trava?
#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 **
Está apontando para uma série de retângulos. Então o acesso deveria ter sido shapes [i] -> draw ();->
foi um erro cometido por um editor.Respostas:
Você não pode indexar assim. Você alocou um array de
Rectangles
e armazenou um ponteiro para o primeiro emshapes
. Ao fazer isso,shapes[1]
você está desreferenciando(shapes + 1)
. Isso não fornecerá um ponteiro para o próximoRectangle
, mas um ponteiro para o que seria o próximoShape
em uma matriz presumida deShape
. Claro, esse é um comportamento indefinido. No seu caso, você está tendo sorte e travando.Usar um ponteiro para
Rectangle
faz com que a indexação funcione corretamente.Se você deseja ter diferentes tipos de
Shape
s no array e usá-los polimorficamente, você precisa de um array de ponteiros para Shape.fonte
Como disse Martinho Fernandes, a indexação está errada. Se, em vez disso, você quiser armazenar uma matriz de Formas, deverá fazer isso usando uma matriz de Formas *, assim:
Observe que você precisa realizar uma etapa extra para inicializar o retângulo, já que inicializar o array apenas configura os ponteiros, e não os próprios objetos.
fonte
Ao indexar um ponteiro, o compilador adicionará a quantidade apropriada com base no tamanho do que está localizado dentro do array. Portanto, diga que sizeof (Shape) = 4 (já que não possui variáveis de membro). Mas sizeof (Rectangle) = 12 (os números exatos provavelmente estão errados).
Então, quando você indexa começando em digamos ... 0 x 0 para o primeiro elemento, quando você tenta acessar o décimo elemento, você está tentando ir para um endereço inválido ou um local que não é o início do objeto.
fonte