C++Guns – RoboBlog

26.04.2013

C++ Guns - explicit keyword und warum man es braucht

Filed under: Allgemein — Tags: , — Thomas @ 08:04

Stell dir vor, du willst die Qt Klasse QPolygonF erweitern damit man noch zusätzlich eine z Koordiante abspeichern kann.
Du erstellst also eine Klasse Polygon die von QPolygonF public erbt.
Dafür hast du dir eine Klasse Point3D erstellt, die eben x,y,z speichert. Und damit man zu Qt's QPointF Klasse kompatibel bleibt, die ja nur 2D arbeitet, kann man ein Point3D aus einem QPointF erstellen. Die Z Koordiante wird entsprechend auf 0 gesetzt.

Nun fängst du an die Klasse Polygon zu implementieren und schreibst eine push_back(Point3D) Funktion. Die x,y Koordinate wird weiter an QPolygonF::push_back() gegeben und den Z Anteil wird irgendwie in Polygon gespeichert.

Um an seine Daten wieder dran zu kommen gibt es mehere Möglichkeiten. Eine davon geht über die Funktion at(). Nun vergisst du aber gerade diese Funktion zu überladen. Kann schonmal passiert. QPolygonF (mit QVector) hat über 30 Funktionen die angepasst werden müssten. Noch dazu haben wir ja keine Zeit und der Compiler wird es auch nicht als Fehler werfen.

Hier die Datenstruktur. Unrelevate Teile hab ich weggelassen.

class Point3D {
public:
...
Point3D(const QPointF & point);
...
};

...
Point3D::Point3D(const QPointF &point)
: x(point.x()), y(point.y()), z(0) {
}

class PolyShape : public QPolygonF {
public:
void push_back ( const Point3D & node);
...
};


Hier mein kleines Testprogramm:

PolyShape poly;
Point3D pointIn(1.,2.,3.);
qDebug() << "put in " << pointIn.x << " "<< pointIn.y << " " << pointIn.z; poly.push_back(pointIn); Point3D pointOut = poly.at(0); qDebug() << "get out" << pointOut.x << " "<< pointOut.y << " " << pointOut.z;

Ich gebe also ein Punkt mit den Koordianten 1, 2, 3 in das Polygon ein und erwarte, dass der selbe Punkt wieder rauskommt.

Starting /home/kater/qtcode/test2/test2...
put in 1 2 3
get out 1 2 0

So ein Mist! Die Z Koordinate ist verschwunden! Aber ist ja auch kein Wunder. Da Polygon kein at() hat, wird die entsprechende Funktion von QPolygonF ausgerufen. Die speichert aber nur QPointF und keine z Koordiante.
Der Fehler passiert, wenn man ein QPointF einem Point3D zuweist. Durch den entsprechenden Konstructor in Point3D klappt das auch, aber wollten wir das so eigentlich?

Man kann mit dem Keyword explicit in diesem Fall einem Compilerfehler erzwingen.

explicit Point3D(const QPointF & point);

main.cpp:62: error: conversion from 'const QPointF' to non-scalar type 'Point3D' requested

Verwende explicit immer dort, wo der Konstructor nur ein Argument hat und es nicht der Copy Ctor ist.

Besser wäre es aber ein anderes Design zu finden. Jede Funktion von QPolygonF zu überladen klingt nicht so gut. Vllt. kommen in der Zukunft ein paar neue hinzu oder es fallen einige weg. Noch mehr Arbeit...

No Comments »

No comments yet.

RSS feed for comments on this post.

Leave a comment

You must be logged in to post a comment.

Powered by WordPress