{"id":2392,"date":"2015-06-10T18:55:24","date_gmt":"2015-06-10T17:55:24","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=2392"},"modified":"2015-06-10T21:54:37","modified_gmt":"2015-06-10T20:54:37","slug":"explicit-constructor-bug-of-the-day-9","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=2392","title":{"rendered":"explicit constructor (Bug of the day 9)"},"content":{"rendered":"<p>Hmm nicht einfach diesen Fehler zu erkl\u00e4ren. Man braucht eine Basis Klasse, zwei abgeleitete Klassen und eine  template Funktionen bei der man den Template Teil vergessen hat.<\/p>\n<p>Die Idee ist folgende:<br \/>\nIrgendeine Funktion die irgendeinen Algorithmus ausf\u00fchrt, bekommt ihre Daten \u00fcber einen Container per Funktionsparameter. Der Container kann alles m\u00f6gliche sein: vector, list, stack array oder eigene Klassen die einen standard Container erweitern.<br \/>\nF\u00fcr den Funktionsparameter, also den Container, benutzt man templates, damit der Algorithmus auf allen m\u00f6glichen Datenstrukturen funktioniert und nur einmal implementiert werden muss.<br \/>\nDas ist g\u00e4ngige Praxis und funktioniert gut.<\/p>\n<p>Nun habe ich zwei neue Klassen erstellt, die von z.B. std::vector erben. Im weiteren ist das die Basis Klasse. Diese Klassen speichern noch eine weitere Information. Welche, ist egal f\u00fcr dieses Beispiel. Nennen wir diese neuen Container Klassen Derived und Derived2. <\/p>\n<p>Die Funktion sieht also so aus:<\/p>\n<pre><code>void func(const Derived &container);<\/code><\/pre>\n<p>Ich benutzt keine Templates, weil ich sie wie gesagt vergessen hatte. Das war Fehler Nr. 1. Der Code compilierte dennoch ;)<\/p>\n<p>Da die neuen Container Klassen Derived und Derived2 beide von der Klasse Base erben, dachte ich, ein Constructor der eine Instanz der Base Klasse entgegen nimmt ist nicht soo verkehrt. Es ist dann bequem m\u00f6glich seine Container mit den Standard Container von c++ zu initialisieren. Das war der zweite Fehler. Es ist im Grunde nicht falsch, nur man braucht es nicht, da wir ja templates nutzen. (Aber nicht implementieren).<\/p>\n<p>Beim dritten Fehler habe ich die Coding Style Regeln nicht beachtet. Die besagt, dass man einen Constructor mit nur einem Argument als explicit deklarieren sollte. Siehe z.B. den Kram von google [1]<\/p>\n<blockquote><p>Normally, if a constructor can be called with one argument, it can be used as a conversion.  Declaring a constructor explicit prevents it from being invoked implicitly as a conversion<\/p><\/blockquote>\n<p>Und genau das ist passiert. Ich habe func() mit einem Derived2 Object aufgerufen, und es wurde mangels templates in ein Derived Object umgewandelt. Dabei gingen nat\u00fcrlich die zus\u00e4tzlichen Informationen verloren, welche diese Klassen speichern sollten.<br \/>\nEine direkte Umwandlung der beiden Derived Klassen hatte ich nicht implementiert, da sie nicht sinnvoll sind.<br \/>\nDie Umwandlung erfolge \u00fcber die Basis Klasse. Ein Derived2 Object <em>ist ein<\/em> Base Object. Und Derived kann mit Base Objecten initialisiert werden.<\/p>\n<p>Das ist alles valid und der Compiler sieht kein Fehler. Aber es sollte zumindest ein Warning f\u00fcr den nicht expliciten Constructor geben. Zumindest bei GNU und clang habe ich nichts dergleichen gefunden. Der Intel Compiler kann es aber wohl [2] (Diagnostic 2304: non-explicit constructor with single argument may cause implicit type conversion).<\/p>\n<p>Was lernen wir daraus? Coding Styles, und sich auch daran halten, retten Leben ;) Und nicht so bescheuert Programmieren ;)<\/p>\n<p>H\u00e4tte man den Fehler durch ausgiebiges Testen der Funktion h\u00e4tte finden k\u00f6nnen? Ja ich denke schon. Aber der Test muss gut sein. In meinem Fall hatte ich nur ein paar einfache Daten getestet und nichts bemerkt. Erst als ich einen anderen Fehler mit dem Debugger suchte ist es mir aufgefallen.<\/p>\n<p>Im Anhang noch der Beispiel Code.<a href=\"http:\/\/roboblog.fatal-fury.de\/wp-content\/uploads\/2015\/06\/explicitctor.cpp_.zip\">explicitctor.cpp.zip<\/a><\/p>\n<p>[1] https:\/\/google-styleguide.googlecode.com\/svn\/trunk\/cppguide.html<br \/>\n[2] https:\/\/software.intel.com\/en-us\/forums\/topic\/335573<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hmm nicht einfach diesen Fehler zu erkl\u00e4ren. Man braucht eine Basis Klasse, zwei abgeleitete Klassen und eine template Funktionen bei der man den Template Teil vergessen hat. Die Idee ist folgende: Irgendeine Funktion die irgendeinen Algorithmus ausf\u00fchrt, bekommt ihre Daten \u00fcber einen Container per Funktionsparameter. Der Container kann alles m\u00f6gliche sein: vector, list, stack array [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-2392","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cpp"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2392","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=2392"}],"version-history":[{"count":4,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2392\/revisions"}],"predecessor-version":[{"id":2399,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2392\/revisions\/2399"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2392"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}