Klausurfrage
-
Hallo zusammen!
Ich lerne gerade für eine Klausur und komme bei folgendem Übungsbeispiel einfach nicht weiter. Ich soll 5 Fehler finden, beschreiben worin genau der Fehler besteht, sowie Korrekturvorschläge erbringen. Jedoch schon beim Finden der Fehler scheitere ich. Vielleicht könnt ihr mir helfen.
Der Code lautet:#include <iostream> #include <vector> struct Point { Point() : x(0.0), y(0.0) {} Point(double px, double py) : x(px), y(py) {} double x; double y; }; class Shape { public: virtual void move(double deltax, double deltay) = 0; virtual void print() = 0; }; class Polygon : public Shape { public: Polygon(int vertices) { m_ptrVertices = new Point[vertices]; m_nvertices = vertices; } Polygon(const Polygon& from) : m_nvertices(from.m_nvertices) { m_ptrVertices = new Point[m_nvertices]; for(int i = 0; i < m_nvertices; ++i) { m_ptrVertices[i] = from.m_ptrVertices[i]; } } Polygon& operator=(const Polygon& from) { if(&from != this) { m_ptrVertices = new Point[m_nvertices]; for(int i = 0; i < m_nvertices; ++i) { m_ptrVertices[i] = from.m_ptrVertices[i]; } } } ~Polygon() {delete[] m_ptrVertices;} void setPoint(int i, const Point& point) { if (i >=0 && i<m_nvertices) { m_ptrVertices[i] = point; } } void print() { for(int i = 0; i < m_nvertices; ++i) { std::cout << m_ptrVertices[i].x << ", " << m_ptrVertices[i].y << std::endl; } std::cout << std::endl; } private: int m_nvertices; Point* m_ptrVertices; }; int main() { Polygon triangle(3); triangle.setPoint(0, Point(0,0)); triangle.setPoint(1, Point(1,0)); triangle.setPoint(2, Point(0.5,1)); triangle.print(); Polygon triangle2(triangle); triangle2.print(); Shape* pshape = new Polygon(1); *pshape = triangle; pshape->print(); delete pshape; return 0; }
-
Welche Fehler findest du denn? Ansonsten ein Tipp: 4 von 5 haben mit der Zuweisung zu tun.
-
So auf die ersten paar Blicke:
Falsch: Verwendung von ungarischer Notation
Point* m_ptrVertices;
Falsch: C-Array (richtig: std::vector)
class Shape { public: virtual void move(double deltax, double deltay) = 0; virtual void print() = 0; };
Falsch: kein virtueller Destruktor
Polygon(int vertices)
Falsch: nicht "explicit"
class Polygon : public Shape {
Falsch: "move" nicht implementiert
-
Fragwürdigen oder veralteten Stil würde ich nicht als Fehler im eigentlichen Sinne bezeichnen.
Aber immerhin sind es jetzt 6, das mit dem virtuellen Destruktor hatte ich nicht gesehen. Ist das wirklich eine Klausuraufgabe? Kommt mir sagen wir mal untypisch vor.
Meine Liste:
move nicht implementiert, dadurch ist Polygon nicht instanziierbar
Zuweisung *pshape = ... nicht möglich, weil Shape keinen Zuweisungsoperator hat
Zuweisungsoperator von Polygon: hat kein return, gibt den alten Speicher nicht frei, übernimmt die Anzahl der Punkte nicht von from
virtueller Destruktor fehlt
-
Bashar schrieb:
Zuweisung *pshape = ... nicht möglich, weil Shape keinen Zuweisungsoperator hat
Und wenn er ihn hätte, würde es zu Slicing kommen. Muss kein Fehler sein, aber i.d.R. will man bei sowas polymorphes Verhalten, schließlich wird anschließend eine rein virtuelle Methode aufgerufen (pshape->print()). Dies würde dann einen "pure virtual function call" ergeben, weil pshape auf ein Objekt vom Typ "Shape" zeigt.
-
daddy_felix schrieb:
Bashar schrieb:
Zuweisung *pshape = ... nicht möglich, weil Shape keinen Zuweisungsoperator hat
Und wenn er ihn hätte, würde es zu Slicing kommen. Muss kein Fehler sein, aber i.d.R. will man bei sowas polymorphes Verhalten, schließlich wird anschließend eine rein virtuelle Methode aufgerufen (pshape->print()). Dies würde dann einen "pure virtual function call" ergeben, weil pshape auf ein Objekt vom Typ "Shape" zeigt.
Nein, das Objekt ist vom Typ Polygon, und das wird sich durch die Zuweisung nicht ändern.
-
oh, das wusste ich nicht. Aber Slicing tritt trotzdem auf, oder?
-
Wenn der Operator nicht virtuell ist, ja. Zuweisung und Polymorphie passen allgemein nur schlecht zusammen.
-
#include <iostream> //Warnung: unnötiges include #include <vector> struct Point { Point() : x(0.0), y(0.0) {} Point(double px, double py) : x(px), y(py) {} double x; double y; }; class Shape { public: //Fehler**: virtueller Destruktor fehlt virtual void move(double deltax, double deltay) = 0; virtual void print() = 0; //Fehler: const fehlt }; class Polygon : public Shape { public: //Warnung: Standardkonstruktor fehlt Polygon(int vertices) { //Fehler: explicit fehlt //Fehler: int ist der falsche Typ //Fehler: Initialisierungsliste fehlt m_ptrVertices = new Point[vertices]; m_nvertices = vertices; } Polygon(const Polygon& from) : m_nvertices(from.m_nvertices) { //Fehler: Initialisierungsliste fehlt m_ptrVertices = new Point[m_nvertices]; for(int i = 0; i < m_nvertices; ++i) { m_ptrVertices[i] = from.m_ptrVertices[i]; } } Polygon& operator=(const Polygon& from) { if(&from != this) { //Fehler**: m_nvertices wird nicht kopiert m_ptrVertices = new Point[m_nvertices]; //Fehler: Speicherleck for(int i = 0; i < m_nvertices; ++i) { m_ptrVertices[i] = from.m_ptrVertices[i]; } } //Fehler**: return fehlt } ~Polygon() {delete[] m_ptrVertices;} void setPoint(int i, const Point& point) { if (i >=0 && i<m_nvertices) { //Fehler: Benutzungsfehler wird verschleiert m_ptrVertices[i] = point; } } void print() { //Warnung: der ostream kann nicht als Argument angegeben werden for(int i = 0; i < m_nvertices; ++i) { std::cout << m_ptrVertices[i].x << ", " << m_ptrVertices[i].y << std::endl; //Fehler: unnötiges flush } std::cout << std::endl; //Warnung: unnötige Leerzeile } //Fehler**: move-Methode fehlt private: int m_nvertices; Point* m_ptrVertices; //Fehler: ein besitzender, roher Zeiger }; int main() { Polygon triangle(3); triangle.setPoint(0, Point(0,0)); triangle.setPoint(1, Point(1,0)); triangle.setPoint(2, Point(0.5,1)); triangle.print(); Polygon triangle2(triangle); triangle2.print(); Shape* pshape = new Polygon(1); //Fehler: ein besitzender, roher Zeiger *pshape = triangle; //Fehler**: Zuweisung ergibt so keinen Sinn pshape->print(); //Fehler: Speicherleck falls das wirft delete pshape; return 0; //Warnung: unnötig }
Mit
Fehler**
sind die fünf markiert, die womöglich in der Aufgabe gemeint sind.