[geloest] Problem mit Konstruktoren



  • Hallo pumuckl,

    vielen Dank fuer deine Tipps. Mir sind hier im Moment selbst einige Fehler aufgefallen, die ich soeben wegbearbeitet habe. Soweit ist der Compiler nur noch nicht gekommen, sonst waeren noch andre Fehler aufgetreten. Die Funktionen conv_from_tcolor sowie conv_to_tcolor existieren also nicht mehr.

    pumuckl schrieb:

    hast du die Übersetzungseinheit von ColorSet dazugelinkt, d.h. deine .cpp mit ins Projekt aufgenommen?

    Ja.

    1. doppelte Unterstriche in Bezeichnern sind für den Compiler bzw. die Implementierung der std-Bibliothek reserviert. Du solltest die entsprechenden Variablennamen also ändern.
      [...]
    2. deine Variablennamen sind zwar schön kurz aber damit auch nichtssagend. Lesbar macht das den Code dadurch nicht unbedingt

    Gut, ersteres werde ich noch abaendern. Die kurzen Variablen sind dennoch aussagekraeftig, da RGB jedem gelaeufig sein sollten. Der Rest ist zunaechst verzichtbar, fuer jeden Programmierer aber meiner Meinung nach aussagefaehig genug. Also halte ich fest: Doppelte Unterstriche entfernen... (dafuer nur einen verwenden?)

    1. <stdio.h> ist nicht im C++-Standard enthalten, der entsprechende Standard-header heißt <cstdio>
    2. <stdio.h>/<cstdio> enthalten die C-I/O Routinen. In C++ kann man das besser/typsicherer/eleganter mit Streams lösen, in deinem Fall fstreams aus dem Header <fstream>

    Werd' ich mir mal anschauen ( fstream ). Das mit stdio.h / cstdio aendere ich ab.

    1. get_rgb liefert einen Pointer auf ein lokales Array, das direkt nach verlassen der Funktion wieder zerstört wird. Den Pointer zu dereferenzieren erzeugt undefiniertes Verhalten.

    Wie gebe ich dann ein Array zurueck?

    1. Du benutzt char-pointer, also C-strings. In C++ gibts die Klasse std::string die Zeichenketten sicherer handhaben kann.

    Allerdings wird das Programm dann auch groesser. Ich nutze beabsichtigt cstrings und bin mir den Konsequenzen bewusst. Eigentlich wird die Klasse auch fuer meine Borland C++Builder-Projekte benutzt, wenn sie denn funktioniert.

    1. Benutze Initialisierungslisten in deinen Konstruktoren.

    Was sind Initialisierungslisten? Kannst du mir bitte ein Beispiel geben?

    1. benutze keine magic numbers sondern definiere dafür Konstanten. Beispielsweise also const unsigned short MAXRGBVALUE = 255; in set_r dann if (r <= MAXRGBVALUE)

    Gut, wird gemacht.

    1. In der main() ist es völlig sinnfrei, einen Pointer auf colorset zu benutzen statt es direkt zu machen

    JA, stimmt schon. Aber andersrum funktioniert's leider auch nicht, hatte ich schon versucht.

    Code wird abgeaendert... [finished]

    E: Uebrigens komme ich nicht aus der C-Schiene.

    Belli schrieb:

    Du mußt die beiden Objektdateien zusammenlinken.

    s.o.



  • heini schrieb:

    1. doppelte Unterstriche in Bezeichnern sind für den Compiler bzw. die Implementierung der std-Bibliothek reserviert. Du solltest die entsprechenden Variablennamen also ändern.
      [...]
    2. deine Variablennamen sind zwar schön kurz aber damit auch nichtssagend. Lesbar macht das den Code dadurch nicht unbedingt

    Gut, ersteres werde ich noch abaendern. Die kurzen Variablen sind dennoch aussagekraeftig, da RGB jedem gelaeufig sein sollten. Der Rest ist zunaechst verzichtbar, fuer jeden Programmierer aber meiner Meinung nach aussagefaehig genug. Also halte ich fest: Doppelte Unterstriche entfernen... (dafuer nur einen verwenden?)

    Wozu überhaupt Unterstriche? r,g,b als Variablennamen sind eventuell noch akzeptabel, allerdings sind die anderen gekürzten Variablennamen zwar nicht so kryptisch, dass man sie nicht verstehen könnte, dennoch lohnt es sich für die Lesbarkeit des Codes, sie auszuschreiben. Man liest den Code schließlich sehr viel öfter, als man ihn schreibt, und dabei ist flüssiges Lesen deutlich angenehmer und fördert das Verständnis noch.
    Und ds hier ist zw. krz abr ncht so gt zu lsn odr?

    1. get_rgb liefert einen Pointer auf ein lokales Array, das direkt nach verlassen der Funktion wieder zerstört wird. Den Pointer zu dereferenzieren erzeugt undefiniertes Verhalten.

    Wie gebe ich dann ein Array zurueck?

    In einem entsprechenden Container. Beispielsweise std::vector oder in dem Fall am besten std::tr1::array (oder boost::array).

    1. Du benutzt char-pointer, also C-strings. In C++ gibts die Klasse std::string die Zeichenketten sicherer handhaben kann.

    Allerdings wird das Programm dann auch groesser. Ich nutze beabsichtigt cstrings und bin mir den Konsequenzen bewusst. Eigentlich wird die Klasse auch fuer meine Borland C++Builder-Projekte benutzt, wenn sie denn funktioniert.

    Der Unterschied in der Größe wird nicht so arg sein dass es sich bei der Ausführung des Programms bemerkbar macht. Auf der anderen Seite vermeidest du mit std::strings häufig vorkommende Fehler wie Bufferüberläufe, Speicherlecks und andere Dinge die mit C-Strings gerne passieren. Du solltest nicht am falschen Ende sparen.

    1. Benutze Initialisierungslisten in deinen Konstruktoren.

    Was sind Initialisierungslisten? Kannst du mir bitte ein Beispiel geben?

    Im Buch/Tutorial deiner Wahl sollte im Abschnitt zu Konstruktoren eigentlich genug darüber stehen.

    1. In der main() ist es völlig sinnfrei, einen Pointer auf colorset zu benutzen statt es direkt zu machen

    JA, stimmt schon. Aber andersrum funktioniert's leider auch nicht, hatte ich schon versucht.

    Das liegt an dem Linkerfehler mit der "undefined reference". Und der kann wie schon gesagt wurde eigentlich nur daran liegen dass aus irgendeinem Grund die Übersetzungseinheit mit den Definitionen aus der colorset.cpp nicht mit ins Projekt gelinkt wird.

    /edit:

    E: Uebrigens komme ich nicht aus der C-Schiene.

    Wer hat dir dann diesen Codestil beigebracht? Mit welchem Buch/Tutorial lernst du C++?



  • Also ich habe jetzt ein neues Testprojekt gestartet, Klassen sind wie oben bezeichnet (gerade nochmal abgeaendert - diesmal ohne der Methode get_rgb ):

    #include <iostream>
    #include "colorset.h"
    
    using namespace std;
    
    int main()
    {
        const int cnt=14;
        unsigned short rgb[3];
        ColorSet cs(cnt,"c:\\test.thm");
        for(int i=0;i<cnt;i++)
        {
            rgb[0]=cs.get_color(i).get_r();
            rgb[1]=cs.get_color(i).get_g();
            rgb[2]=cs.get_color(i).get_b();
            cout<<"DS "<<i+1<<": RGB("<<rgb[0]<<","<<rgb[1]<<","<<rgb[2]<<")"<<endl;
        }
        cout<<"Saving file: ";
        cout<<cs.save_other_file("c:\\test2.thm")<<endl;
        getchar();
        return 0;
    }
    

    Die cpp -Dateien sind dem Projekt angefuegt und der Compiler ging diese auch durch, jedenfalls gab er Fehlermeldungen aus, weil ich an einer Stelle eine normale statt einer geschweiften Klammer gesetzt hatte, also kennt der Compiler die cpp -Dateien. Nun hier die aktuelle, komplette Fehlerliste:

    obj\Debug\main.o||In function `main':|
    c:\main.cpp|10|undefined reference to `ColorSet::ColorSet(int, char*)'|
    c:\main.cpp|13|undefined reference to `ColorSet::get_color(int)'|
    c:\main.cpp|14|undefined reference to `ColorSet::get_color(int)'|
    c:\main.cpp|15|undefined reference to `ColorSet::get_color(int)'|
    c:\main.cpp|19|undefined reference to `ColorSet::save_other_file(char*)'|
    ||=== Build finished: 5 errors, 0 warnings ===|
    

    pumuckl schrieb:

    Wozu überhaupt Unterstriche? r,g,b als Variablennamen sind eventuell noch akzeptabel, allerdings sind die anderen gekürzten Variablennamen zwar nicht so kryptisch, dass man sie nicht verstehen könnte, dennoch lohnt es sich für die Lesbarkeit des Codes, sie auszuschreiben.

    Nunja, es ist eine kleine Klasse, und ich mag keine langen Variablen. Das ist halt Geschmackssache. Und die Unterstriche sind fuer mich, dass ich weiss, dass es sich um eine private Eigenschaft innerhalb der Klasse handelt.

    Und ds hier ist zw. krz abr ncht so gt zu lsn odr?

    Also ich kann das sehr gut lesen. 😉 😛

    Wie gebe ich dann ein Array zurueck?

    In einem entsprechenden Container. Beispielsweise std::vector oder in dem Fall am besten std::tr1::array (oder boost::array).

    Muss ich mir nochmal anschauen. Die Funktion habe ich erstmal rausgenommen.

    Allerdings wird das Programm dann auch groesser. Ich nutze beabsichtigt cstrings und bin mir den Konsequenzen bewusst. Eigentlich wird die Klasse auch fuer meine Borland C++Builder-Projekte benutzt, wenn sie denn funktioniert.

    Der Unterschied in der Größe wird nicht so arg sein dass es sich bei der Ausführung des Programms bemerkbar macht. Auf der anderen Seite vermeidest du mit std::strings häufig vorkommende Fehler wie Bufferüberläufe, Speicherlecks und andere Dinge die mit C-Strings gerne passieren. Du solltest nicht am falschen Ende sparen.

    Werde drueber nachdenken. Dennoch steht das hier ja nicht zur Debatte. Der Compiler meckert, dass er die Funktionen fuer die Klasse nicht findet, obwohl ich die Dateien hinzugefuegt habe usw.

    Was sind Initialisierungslisten? Kannst du mir bitte ein Beispiel geben?

    Im Buch/Tutorial deiner Wahl sollte im Abschnitt zu Konstruktoren eigentlich genug darüber stehen.

    Vielleicht wuerde ich es ja kennen, nur die Bezeichnung als solche, Initialisierungslisten , sagt mir nichts. Ich werd' recherchieren, wenn ich Zeit dafuer finde.

    Das liegt an dem Linkerfehler mit der "undefined reference". Und der kann wie schon gesagt wurde eigentlich nur daran liegen dass aus irgendeinem Grund die Übersetzungseinheit mit den Definitionen aus der colorset.cpp nicht mit ins Projekt gelinkt wird.

    Eigentlich ist gut.

    Wer hat dir dann diesen Codestil beigebracht?

    Ich selbst, in meiner Praxis. Bisher bin ich damit ganz gut gefahren, nicht nur bei C++, sondern auch bei PHP, Javascript, Delphi usw. Natuerlich ist das allgemein kein guter Stil.

    Mit welchem Buch/Tutorial lernst du C++?

    Im Moment gar nicht weiter. Ich schreibe nur, und wenn ich mal etwas nicht weiss, recherchiere ich im World Wide Web. Und wenn ich nicht fuendig werde, frage ich z.B. hier. Dazu ist das Usenet ja da.



  • Welchen Compiler und welche IDE benutzt du?



  • Code::Blocks 8.02



  • Das ist die IDE. welcher Compiler? Gibt dir die IDE irgendwo aus wie sie den Compiler aufruft?



  • Achso. Dev-C++ wird verwendet, die letzte stabile Version. Sorry.



  • heini schrieb:

    Achso. Dev-C++ wird verwendet, die letzte stabile Version. Sorry.

    Dev-C++ ist eine andere IDE. Die allerdings schon seit 2005 nicht mehr weiterentwickelt und entsprechend veraltet ist.

    Der Compiler der darunter hängt ist dann vermutlich ein gcc/MinGW.



  • Jap, das meinte ich. Sorry.

    E: Ich bin jetzt uebrigens auf vector umgestiegen, was das dynamische Array _c in ColorSet angeht, was natuerlich nichts am Problem aendert.

    Werde morgen mal probieren, die Klassendefinitionen mit in das Projekt selbst zu schreiben.



  • So, wenn ich die Klasse (mittlerweile einige Aenderungen) nun direkt in das Projekt kopiere, funktioniert alles.

    Irgendwie scheine ich ein Pechvogel zu sein, was die IDE oder den Compiler angeht; nach dem Fehlverhalten des BCB5 nun selbes Problem in anderer Sache mit Code::Blocks. 🙄

    Soll heissen: Thema ist geloest.



  • heini schrieb:

    Irgendwie scheine ich ein Pechvogel zu sein, was die IDE oder den Compiler angeht; nach dem Fehlverhalten des BCB5 nun selbes Problem in anderer Sache mit Code::Blocks. 🙄

    bestimmt x)


Anmelden zum Antworten