kurze frage zum default-konstruktor



  • Core(){ 
      c=component();
    };
    

    ist das gleiche wie

    Core():c(){ 
      c=component();
    };
    

    Jetzt solltest du die beiden Konstruktor-Aufrufe sehen.



  • okay, danke schön, aber dann hätte ich noch eine frage: wie kann ich einen konstruktor ohne parameter so deklarieren, dass er nicht automatisch zum default-konstruktor wird, sondern darauf wartet, bis ich den explizit aufrufe? (wäre meiner meinung nach sowas wie versuch, zwei überladene funktionen mit der gleichen argumentenliste zu erstellen) aber vielleicht gibts für die konstruktoren irgendeine ausnahmeregelung? Weil, in meinem fall macht es keinen sinn, dass dieses objekt sich automatisch irgendwo materialisiert, und es macht genausowenig sinn, in den konstruktor irgendwelche sinnlose argumente einzubauen...

    thx@all

    edit: obwohl, wenn ich mir das genauer überlege... das macht eigentlich keine wirklichen schwierigkeiten (der konstruktor verändert jetzt keine globalen variablen oder irgendsowas) das ist eigentlich ein rein "kosmetischer" fehler: diese spontane konstruktor aufrufe werfen meine logfile durcheinander, und das nervt mich, weil ich bei meinem projekt sowieso kaum noch durchblicke...



  • Aus welchem Grund willst du den Default Konstruktor explizit aufrufen?? Das macht doch irgendwie keinen Sinn, find ich. Der Sinn von Konstruktoren ist, dass keine Elemente uninitialisiert bleiben. Wenn du das umgehst sind sie sinnlos.



  • nein, leider falsch verstanden, was ich meine...
    also... ich will da insgesamt zwei konstruktoren haben: einen default-konstruktor, der mich eh nicht interessiert und von mir aus komplett wegfallen konnte (ich brauch den nich, der muss aber sein, weil das programm an sich nicht anders funktioniert) + meinen eigenen konstruktor, der zwar durchaus sinnvolles macht, jedoch keine parameter benötigt (und somit für den compiler wie ein default-konstruktor aussieht)

    //default: den brauch ich eigentlich nicht
    componentX(){ /*von mir aus, alles auf 0 setzen, ist mir wurscht*/ }
    componentX(){ 
    /*hier werden einige wichtige operationen ausgeführt.
    davon will ich eine bemerkung in meiner Logfile stehen haben
    und zwar zu einem zeitpunkt, wo es einem gewöhnlichen leser 
    sinnvoll und logisch erscheint*/
    
    /*problem: compiler erkennt diesen konstruktor als dähmlichen
    default construktor, den er selbsständig aufruft*/
    
    /*dadurch erscheinen die Lofile einträge aus "componentX"
    sogar vor den meldungen des "Core"-konstruktors, was nicht nur 
    für einen gewöhnlichen leser, sondern auch für mich verdammt 
    verwirrend aussieht :( 
    */
    }
    

    aber dagegen kann ich nicht viel machen, bzw. zB einen sinnlosen argument in den konstruktor einbauen:

    componentX(
    int neverUsedNonSenceArgument_forcingCompilerToWaitForAnExplicitCall)
    {
    //mein sinnvoller konstruktor
    }
    

    dann wird er nicht als default construktor erkannt, und der compiler wartet, bis ich den explicit aufrufe. Das ist aber doof und hässlich. Gibts da echt nichts, was man tun könnte?



  • Hmm, nochmal also, du willst also ein Objekt zwar schon anlegen, aber erst an bestimmter Stelle den Konstruktor aufrufen, weil im Konstruktor Logfiles angelegt werden, die eben erst an der Stelle Sinn machen. Ist das nun soweit korrekt?

    Dann würde ich fragen: warum muss das ein Konstruktor machen? warum nicht einfach eine Methode writeLogs() und das ganze ist in Ordnung?

    (Bevor jetzt die Antwort kommt: Weil ich da noch einige Werte "nachinitialisiere" -> dann eben noch eine Methode set() oder setandwriteLogs() oder was auch immer.)

    Ansonsten können die Profis hier vielleicht mehr helfen, allerdings würde ich dann mehr Code posten. Ich weisz ja nicht (als Anfänger) aber das hört sich doch mehr nach Designfehler als nach Sprachmittelproblem an.

    EDIT: kann man nen Konstruktor explicit machen?



  • ja, klar, ich könnte auch so vorgehen:

    -"Core" konstruieren, und damit fünfzig default-construktoren von component1 bis component50 aufrufen, die jedoch an sich nichts machen und auch nichts in die logfile schreiben.

    -für jedes component1-component50 objekt eine Init() funktion schreiben, die dann genau das tut, was zur zeit meine ganzen konstruktoren übernehmen

    -programm laufen lassen

    -Exit() für alle components aufrufen

    -destruktoren automatisch aufrufen lassen.

    Okay. Hab eigentlich nichts gegen die vorgehensweise. In meinem fall müsste ich dann aber 50 konstruktoren in eine Init() funktion umschreiben, und zwar weil bei einem einzigen objekt der konstruktor keine parameter benötigt, und deswegen als default-konstruktor angesehen wird (bei allen anderen components besteht die verwechslungsgefahr gar nicht, weil die alle irgendwelche parameter benötigen)

    ps: okay, 50 sinds bestimmt nicht, ich hätte aber irgendwie trotzdem keine lust, mein ganzes programm nochmal umzustrukturieren 🙄

    edit: und vor allem, weil es nur ein doofer kosmetischer fehler ist, der an sich nichts ausmacht... 😞



  • Wie Shinja sagte:
    Willst du das ein Konstruktor nicht impliziit aufgerufen wird musst du ihn explizit machen:

    explicit componentX();
    

    Gruß
    Don06



  • Hallo Andrey,

    schreib doch nochmal auf, was das Programm leisten soll. Am besten postest du den ganzen Code, wenn er nicht zu lang ist!



  • /*dadurch erscheinen die Lofile einträge aus "componentX"
    sogar vor den meldungen des "Core"-konstruktors, was nicht nur 
    für einen gewöhnlichen leser, sondern auch für mich verdammt 
    verwirrend aussieht :(
    

    aha, ein kosmetisches problem und mangel an wahrsagerischen fähigkeiten beim logfilelesen. was du brauchst, ist einfach ne meldung, daß der Core-Konstruktor dran schuld ist, daß jetzt jene component konstruiert wird.

    nundenn, nimm dies, pursche!

    #include <iostream>
    using namespace std;
    
    template<typename T>
    struct ConstructorLogger{
       ConstructorLogger(){
          cout<<"an object of "<<typeid(T).name()<<" will be created\n";
       }
    };
    class Component:private ConstructorLogger<Component>{
    public:
    	Component(){
    		cout<<"Konstruktor von Component\n";
    	}
    };
    class Core:private ConstructorLogger<Core>{
       Component c;
       public:
       Core(){
    	   cout<<"Ich mache Dir den Core!\n";
       }
    };
    
    int main(){
    	Core core;
    }
    

    ausgabe:

    an object of class Core will be created
    an object of class Component will be created
    Konstruktor von Component
    Ich mache Dir den Core!
    


  • @Don06: "explicit" davorschreiben, und dann klappts schon? damit nehme ich dem programm das recht, es selbsständig aufzurufen? okay, dann ist es genau das, was ich die ganze zeit schon wissen wollte, thx a lot! 🙂 👍

    @WilMen: Ne, das ding ist wirklich ein bissl groß, um das einfach hierreinzuposten, ausserdem würde das gar nichts bringen. Aber ich würde trotzdem gerne was loswerden:
    ist das in ordnung, den code so zu strukturieren, dass ich die ganzen funktionen etc. auf verschiedene klassen verteile, und dann jeweils nur einen objekt dieser klasse erstelle? Ich hab es mir irgendwie in Java angewöhnt, für alles eine klasse anzulegen... Hat auch einen vorteil gegenüber namespaces, weil man da zwische privat und public unterscheiden kann... Aber gibt es evtl sinnvollere methoden, den code zu gliedern?

    @volkard: Danke für den vorschlag, aber leider ist das nicht ganz das, was ich will, weil die konstruktoren meiner klassen viel mehr in die logfile schreiben, als dass sie aufgerufen wurden (beim einen ist es zum beispiel so, dass direkt im konstruktor ermittelt wird, was der benutzer für eine grafikkarte hat, und wie man da am besten grafik auf den bildschirm zaubert, an dieser stelle kommen da schon n paar große tabellen mit allen einstellungen zusammen, die ich gerne in der logfile hätte, falls es auf irgendeinen graKa dann nicht läuft... )

    Aber trotzdem danke für alle ideen und vorschläge, ich werde es mal mit "explicit" versuchen, hoffe mal, dass es genau das bewirkt, was ich will.

    🤡



  • nein, "explicit" bringts auch nich, es wird immer noch als default-construktor erkannt. Naja, egal... habs mir jetzt noch einmal genauer angeschaut, und bin zum schluss gekommen, dass ich das alles dann vielleicht doch in separate

    bool component::Init()
    

    funktionen auslagere. Dann bleiben die konstruktoren ebn sogut wie leer. Ist nich schlimm, muss halt n bissl code hinundher copypasten... 🙄

    trotzdem danke für alle vorschläge! 🙂



  • Die Angewohnheit alles in Klassen einzubetten ist gut. Ich kenne keine Argumente die dagensprechen. OOP ist die Zukunkft!



  • naja... gerade dass ist ja keine OOP, sondern eher missbrauch von "klassen" als "namespace", oder sehe ich das falsch? 😃



  • mein vorschlag erlaubt doch, daß alles wie bisher in den konstruktoren geloggt wird. ich schreibe nur ne zeile davor, woher dieser component-konstruktor gerade aufgerufen wurde.

    Andrey schrieb:

    nein, "explicit" bringts auch nich, es wird immer noch als default-construktor erkannt. Naja, egal... habs mir jetzt noch einmal genauer angeschaut, und bin zum schluss gekommen, dass ich das alles dann vielleicht doch in separate

    bool component::Init()
    

    funktionen auslagere. Dann bleiben die konstruktoren ebn sogut wie leer. Ist nich schlimm, muss halt n bissl code hinundher copypasten... 🙄

    tu das nicht. das ist ein abschüssiger weg in den game-coderz-sumpf. du willst doch nicht so schlecht wie TGGC werden?



  • Nein, das ist Datenkapselung! Wenn du nun auch noch alle Eigenschaften der Klasse als "private" deklarierst und diese nur über Methoden ansprechen kannst, dann hälst du dich an strickte OOP.



  • @ volkard: ja, der vorschlag ist eigentlich schon ganz gut, aber immer noch nicht ganz das, was ich gerne hätte. Hier vllt. noch ein kleiner beispiel, um zu verdeutlichen, was mich an der ganzen geschichte so sehr nervt:

    //mein code
    class Core{
      Core(){
        logfile->write( "Core constructor called!");
        c1=component1(x,y,z);
        c2=component2(); //genauso bedeutend, wie c1, braucht abre keine argumente
        c3=component3(a,b,c);
        c4=component4( thisHandle, thatHandle, pointerToSomeImportantStuff);
      }
    }
    

    ausgabe in die logfile:

    Hi, im component2!
    ======Core Block============
    = Core constructor called!
    = Hi, im component1!
    = Hi, im component2!
    = Hi, im component3!
    = Hi, im component4!
    ===End of Core Block========
    

    auch wenn jetzt ausgegeben wird, dass das alles teil vom core-konstruktor ist, tanzt component2 aus der reihe, weil sein normaler konstruktor für den compiler wie ein default konstruktor aussieht. Das hat konkret zur folge, dass die ganzen tabellen mit den parametern der GraKa zwei mal ausgegeben werden. Und das will ich irgendwie verhindern.

    ?1.) soll ich da vllt doch einen sinnlosen argument einbauen? 🙄
    ?2.) was ist "game-coderz-sumpf" und was ist an dem so schlimm? 😃

    @WilMen: okay, na dann bin ich ja beruhigt 🙂

    danke an alle nochmal...



  • Don06 schrieb:

    Wie Shinja sagte:
    Willst du das ein Konstruktor nicht impliziit aufgerufen wird musst du ihn explizit machen:

    explicit componentX();
    

    Gruß
    Don06

    Das stimmt so nicht. explicit kann im Zusammenhang (und im Moment nur in dem) mit Konstruktoren die einen Parameter besitzen benutzen (zwei Parameter + default Wert geht auch). Dies bewirkt, dass der Konstruktor nicht zur impliziten Typumwandlung benutzt wird.



  • //mein code
    class Core{
      Core()
     :c1(component1(x,y,z))
     ,c2()
     ,c3(a,b,c)
     ,c4(thisHandle, thatHandle, pointerToSomeImportantStuff)
     {
        log<<"Core constructor called\n";
        log<<"===End of Core Block========\n";
     }
    }
    

    ausgabe in die logfile:

    an object of class Core will be created
    = Hi, im component1!
    = Hi, im component2!
    = Hi, im component3!
    = Hi, im component4!
    = Core constructor called!
    ===End of Core Block========
    

    das ist aber nicht lecker. solche mega-objekte mit komplexen konstruktoren allein in initialisiererlisten zu bauen, wird unübersichtlich. da muß man dann ein wenig überlegen, wie man das loswird. gerne mit Component1 createCOmponent1(...). auch gerne für Core selber. auch gerne daß die members von Core nur zeiger sind (smart-pointers natürlich).

    recht wirchtig scheint mir für dich noch zu sein, daß du im logfile immer einrückungen mitführst.

    an object of class Core will be created
       Hi, im component1!
          suche grafikkarte
          hab eine gefunden
             name: ...
             herstellerkennung: ...
       Hi, im component2!
       Hi, im component3!
       Hi, im component4!
    

    ?1.) soll ich da vllt doch einen sinnlosen argument einbauen? 🙄

    das hilft nicht wirklich. aber probier's aus, das schadet nicht.

    was ist "game-coderz-sumpf" und was ist an dem so schlimm?

    mächtig viele game-coderz haben die grundlagen von c++ nicht begriffen und sind bloß stümper, was das programmieren angeht. kommt davon, wenn man die probleme nicht löst, sondern auswicht, um schnell bunte bildchen zu sehen.



  • das ist aber nicht lecker. solche mega-objekte mit komplexen konstruktoren allein in initialisiererlisten zu bauen, wird unübersichtlich. da muß man dann ein wenig überlegen, wie man das loswird.

    sry, verstehe nicht ganz, was du jetzt konkret mit "initialisiererliste" meinst 🙄

    recht wichtig scheint mir für dich noch zu sein, daß du im logfile immer einrückungen mitführst.

    thx 😉 , aber mach dir keine sorgen, an der logfile wird es nicht liegen, wenn ich bei den ganzen componenten-hierarchien da nicht mehr durchblicke, die logfile habe ich imho ganz ordentlich hinbekommen, html formattiert, mit farben/überschriften und vor allem: "blöcken"
    "blöcke": das sind bei mir solche html-tabellen mit einer überschrift und einer einzigen tabellen-zelle, die von einem dicken rand umgeben ist. ich wollte in der logfile insgesamt drei große blöcke haben: "Init" "Loop" "Exit"
    der construktor von "Core" war im grunde für den gesammten ersten block verantwortlich. Doch dann habe ich festgestellt, dass manche meldungen aus component-konstruktoren vor dem "init" block erscheinen, und das war eigentlich genau das, was mich so aufgeregt hat 😞

    game-coderz-sumpf

    wieder danke für den tipp, den wunsch, einen haufen bunter dreiecke zu sehen, habe ich bereits nach 3 wochen mit C++ befriedigt, mir reichts erstmal :p



  • Nur so nen Tipp für den nächsten Logger:

    Schreib die Logging-Einträge in eine XML File.

    Schreib dir mit Hilfe von etwas (X)HTML+JavaScript+XSLT einen LogViewer:
    Das (X)HTML + JavaScript erzeugt ein Formular indem du die Logdatei angibst + optionale Filteroptionen. Beim Absenden ruft JavaScript den XSLT Parse auf mit den Filtern und der XML Datei. Dieser parst die XML Datei wendet den Filter an und spuckt (X)HTML aus welches du mittels JavaScript dann dynamisch der Seite hinzufügen kannst.

    So hast du ein sehr sehr mächtiges logging System 🙂


Anmelden zum Antworten