{"id":1769,"date":"2013-04-26T08:53:23","date_gmt":"2013-04-26T07:53:23","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=1769"},"modified":"2017-05-24T11:22:45","modified_gmt":"2017-05-24T10:22:45","slug":"explicit-keyword-und-warum-man-es-braucht","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=1769","title":{"rendered":"C++ Guns - explicit keyword und warum man es braucht"},"content":{"rendered":"<p>Stell dir vor, du willst die Qt Klasse QPolygonF erweitern damit man noch zus\u00e4tzlich eine z Koordiante abspeichern kann.<br \/>\nDu erstellst also eine Klasse Polygon die von QPolygonF public erbt.<br \/>\nDaf\u00fcr 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.<\/p>\n<p>Nun f\u00e4ngst 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. <\/p>\n<p>Um an seine Daten wieder dran zu kommen gibt es mehere M\u00f6glichkeiten. Eine davon geht \u00fcber die Funktion at(). Nun vergisst du aber gerade diese Funktion zu \u00fcberladen. Kann schonmal passiert. QPolygonF (mit QVector) hat \u00fcber 30 Funktionen die angepasst werden m\u00fcssten. Noch dazu haben wir ja keine Zeit und der Compiler wird es auch nicht als Fehler werfen.<\/p>\n<p>Hier die Datenstruktur. Unrelevate Teile hab ich weggelassen.<br \/>\n<code><\/p>\n<p>class Point3D {<br \/>\npublic:<br \/>\n   ...<br \/>\n  Point3D(const QPointF & point);<br \/>\n   ...<br \/>\n};<\/p>\n<p>...<br \/>\n<span style=\"color:blue\">Point3D::Point3D(const QPointF &point)<br \/>\n    : x(point.x()), y(point.y()), z(0) {<br \/>\n}<\/span><\/p>\n<p>class PolyShape : public QPolygonF {<br \/>\npublic:<br \/>\n    void push_back ( const Point3D & node);<br \/>\n...<br \/>\n};<\/p>\n<p><\/code><br \/>\nHier mein kleines Testprogramm:<br \/>\n<code><br \/>\n    PolyShape poly;<br \/>\n    Point3D pointIn(1.,2.,3.);<br \/>\n    qDebug() << \"put in \" << pointIn.x << \" \"<< pointIn.y << \" \" << pointIn.z;\n    poly.push_back(pointIn);\n\n    Point3D pointOut = poly.at(0);\n    qDebug() << \"get out\" << pointOut.x << \" \"<< pointOut.y << \" \" << pointOut.z;\n<\/code><\/p>\n<p>Ich gebe also ein Punkt mit den Koordianten 1, 2, 3 in das Polygon ein und erwarte, dass der selbe Punkt wieder rauskommt.<\/p>\n<blockquote><p>\nStarting \/home\/kater\/qtcode\/test2\/test2...<br \/>\nput in  1   2   3<br \/>\nget out 1   2   <span style=\"color:red;\">0<\/span>\n<\/p><\/blockquote>\n<p>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.<br \/>\nDer Fehler passiert, wenn man ein QPointF einem Point3D zuweist. Durch den entsprechenden Konstructor in Point3D klappt das auch, aber wollten wir das so eigentlich?<\/p>\n<p>Man kann mit dem Keyword explicit in diesem Fall einem Compilerfehler erzwingen.<br \/>\n<code><br \/>\n<span style=\"color:red;\">explicit<\/span> Point3D(const QPointF & point);<br \/>\n<\/code><\/p>\n<blockquote><p>\nmain.cpp:62: error: conversion from 'const QPointF' to non-scalar type 'Point3D' requested\n<\/p><\/blockquote>\n<p>Verwende explicit immer dort, wo der Konstructor nur ein Argument hat und es nicht der Copy Ctor ist.<\/p>\n<p>Besser w\u00e4re es aber ein anderes Design zu finden. Jede Funktion von QPolygonF zu \u00fcberladen klingt nicht so gut. Vllt. kommen in der Zukunft ein paar neue hinzu oder es fallen einige weg. Noch mehr Arbeit...<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stell dir vor, du willst die Qt Klasse QPolygonF erweitern damit man noch zus\u00e4tzlich eine z Koordiante abspeichern kann. Du erstellst also eine Klasse Polygon die von QPolygonF public erbt. Daf\u00fcr 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 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17,12],"class_list":["post-1769","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cpp","tag-qt"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1769","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1769"}],"version-history":[{"count":28,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1769\/revisions"}],"predecessor-version":[{"id":3041,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1769\/revisions\/3041"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1769"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}