Ich ging heute zu einem Vorstellungsgespräch und bekam diese interessante Frage.
Warum stürzt dieser Code ab, abgesehen von dem Speicherverlust und der Tatsache, dass es keinen virtuellen dtor gibt?
#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 **
es auf eine Reihe von Rechtecken zeigt. Dann sollte der Zugriff Formen [i] -> draw () gewesen sein;->
war ein Fehler eines Redakteurs.Antworten:
Sie können so nicht indizieren. Sie haben ein Array von zugewiesen
Rectangles
und einen Zeiger auf das erste in gespeichertshapes
. Wenn Sie dies tunshapes[1]
, dereferenzieren Sie(shapes + 1)
. Dies gibt Ihnen keinen Zeiger auf den nächstenRectangle
, sondern einen Zeiger auf den nächstenShape
in einem vermuteten Array vonShape
. Dies ist natürlich undefiniertes Verhalten. In Ihrem Fall haben Sie Glück und bekommen einen Absturz.Wenn Sie einen Zeiger verwenden,
Rectangle
funktioniert die Indizierung ordnungsgemäß.Wenn Sie verschiedene Arten von
Shape
s im Array haben und diese polymorph verwenden möchten, benötigen Sie ein Array von Zeigern auf Shape.quelle
Wie Martinho Fernandes sagte, ist die Indizierung falsch. Wenn Sie stattdessen ein Array von Shapes speichern möchten, müssen Sie dazu ein Array von Shape * verwenden, wie folgt:
Beachten Sie, dass Sie einen zusätzlichen Schritt zum Initialisieren des Rechtecks ausführen müssen, da beim Initialisieren des Arrays nur die Zeiger und nicht die Objekte selbst eingerichtet werden.
quelle
Beim Indizieren eines Zeigers fügt der Compiler den entsprechenden Betrag hinzu, der auf der Größe der Elemente im Array basiert. Nehmen wir also an, dass sizeof (Shape) = 4 ist (da es keine Mitgliedsvariablen gibt). Aber sizeof (Rechteck) = 12 (genaue Zahlen sind wahrscheinlich falsch).
Wenn Sie also ab ... 0x0 für das erste Element indizieren, versuchen Sie beim Zugriff auf das 10. Element, zu einer ungültigen Adresse oder einem Ort zu wechseln, der nicht der Anfang des Objekts ist.
quelle