Je suis allé à un entretien d'embauche aujourd'hui et j'ai reçu cette question intéressante.
Outre la fuite de mémoire et le fait qu'il n'y ait pas de dtor virtuel, pourquoi ce code plante-t-il?
#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 **
Il pointe vers un tableau de rectangles. Ensuite, l'accès aurait dû être des formes [i] -> draw ();->
était une erreur commise par un éditeur.Réponses:
Vous ne pouvez pas indexer comme ça. Vous avez alloué un tableau de
Rectangles
et stocké un pointeur vers le premier dansshapes
. Lorsque vous faitesshapes[1]
vous déréférencer(shapes + 1)
. Cela ne vous donnera pas un pointeur vers le suivantRectangle
, mais un pointeur vers ce qui serait le suivantShape
dans un tableau présumé deShape
. Bien sûr, ce comportement n'est pas défini. Dans votre cas, vous avez de la chance et vous avez un accident.L'utilisation d'un pointeur sur
Rectangle
fait fonctionner correctement l'indexation.Si vous voulez avoir différents types de
Shape
s dans le tableau et les utiliser de manière polymorphe, vous avez besoin d'un tableau de pointeurs vers Shape.la source
Comme l'a dit Martinho Fernandes, l'indexation est erronée. Si vous souhaitez à la place stocker un tableau de formes, vous devez le faire en utilisant un tableau de formes *, comme ceci:
Notez que vous devez faire une étape supplémentaire d'initialisation du Rectangle, car l'initialisation du tableau ne configure que les pointeurs, et non les objets eux-mêmes.
la source
Lors de l'indexation d'un pointeur, le compilateur ajoutera le montant approprié en fonction de la taille de ce qui se trouve à l'intérieur du tableau. Disons donc que sizeof (Shape) = 4 (car il n'a pas de variables membres). Mais sizeof (Rectangle) = 12 (les nombres exacts sont probablement faux).
Ainsi, lorsque vous indexez à partir de disons ... 0x0 pour le premier élément, lorsque vous essayez d'accéder au 10ème élément, vous essayez d'accéder à une adresse invalide ou à un emplacement qui n'est pas le début de l'objet.
la source