exklusiver Konstruktorenaufruf



  • Morgen!

    Mal ne recht blöde Frage:
    Angenommen ich hätte folgendes Codebeispiel:

    #ifndef MY_EXCEPTION_H
    #define MY_EXCEPTION_H
    
    #include "TException.h"
    
    class TMyException : public TException
    {
      public:
      TMyException(char *message) : TException(message)
      {
         TException::TException("andere Fehlermeldung");
      }
    
      protected:
      //nix
    
      private:
      //nix
    };
    
    #endif
    

    Warum hat denn der zweite Konstruktorenaufruf der Elternklasse TException
    im Konstruktor von TMyException keine Auswirkungen auf die Fehlermeldung?
    Wenn ich die Meldung ausgeben lasse, erscheint lediglich der ursprüngliche
    Wert von '*message'!

    Grüße,
    TS++



  • Hallo,
    mir scheint du unterliegst hier einem klassischen Irrtum.

    TException::TException("andere Fehlermeldung");

    Diese Zeile im Ctor von TMyException ruft *nicht* erneut den Basisklassenctor von TException auf. Das Basisklassenobjekt ist mit dem Eintreten in den Ctor von TMyException bereits vollständig erzeugt. Und da man Konstruktoren nicht explizit aufrufen kann, gibt es keine Möglichkeit den Ctor der Basisklasse nocheinmal für dieses Objekt laufen zu lassen.
    In der zitierten Zeile wird lediglich ein temporäres Objekt der Klasse TException erzeugt, welches am Ende der Anweisung (also beim Semikolon) schon wieder stirbt.
    Dieses temporäre Objekt hat aber *nichts* mit dem TMyException-Objekt zu tun, dass du gerade erzeugst.



  • Danke für die Antwort!

    Besteht die Möglichkeit einen derartigen Effekt auf irgendeine andere
    Weise doch zu erreichen?

    Könnte ja evtl. nützlich sein:

    TClass::TClass()
    {
       //hier: Wert x berechnen
       TBaseClass::TBaseClass(x);
    }
    

    Bei dem Beispiel würde ja zunächst der Standardkonstruktor von
    TBaseClass aufgerufen, welcher in dem Beispiel hier, das unterstelle ich
    einfach mal, nichts macht. Erst im Konstruktor der Kindklasse TClass
    würde ich dann einen konkreten Wert x vorbereiten, der dann an den
    entsprechenden Konstruktor der Basisklasse übergeben wird.
    Ich wüsste jetzt nicht, wie ich einen derartigen Effekt anders erreichen
    sollte!

    Grüße,
    TS++



  • Bedeutet das jetzt, ich müsste den Code auf folgende Art und Weise
    modifizieren?
    (Austauschen der Meldung kann natürlich viel leichter erreicht werden!
    Mir geht es jetzt mehr um die bereits genannte Kernproblemstellung)

    #ifndef MY_EXCEPTION_H
    #define MY_EXCEPTION_H
    
    #include "TException.h"
    
    class TMyException : public TException
    {
      public:
      TMyException(char *message) : TException(replaceMessage(message))
      {
         //nix
      }
    
      protected:
      //nix
    
      private:
      char *replaceMessage(char *message)
      {
         strcpy(message,"andere Fehlermeldung");
         return(message);
      }
    };
    
    #endif
    

    Grüße,
    TS++

    [ Dieser Beitrag wurde am 13.04.2003 um 12:04 Uhr von TS++ editiert. ]



  • ja du bist auf den richtigen weg, nur gefält mir nicht wie du mit char * umgehst
    wenn jemand z.b.

    throw TMyException(".");
    

    du aber in replaceMessage "andere Fehlermeldung" rein schreibst, mal ganz davon abgesehen das man in string literare nicht reinschreiben darf



  • Das in dem von mir gewählten Beispiel das Ersetzen der Nachricht
    eigentlich sinnlos ist und dass die Art und Weise, wie die Nachricht
    ersetzt wird, äußerst umständlich ist, ist mir schon bewusst.
    Das die Nachricht mittels einer zusätzlichen Methode ersetzt wird,
    war sogar beabsichtigt.

    Worauf es mir in dem Beispiel ankam, war die Fähigkeit, im Konstruktor
    einer Kindklasse TClass die Übergabeparameter für den Konstruktor der
    Elternklasse TBaseClass zu bestimmen, mit evtl. sehr aufwändigen
    Algorithmen, und diese Parameter an den Elternkonstruktor zu übergeben.

    Bei folgendem Fall muss man sich ja keine weiteren Gedanken machen:

    TClass::TClass() : TBaseClass(1)
    {
       //nix
    }
    

    Hier kann ich ja bereits beim Entwickeln genau fessetzen, mit welchem Parameter
    der Elternkonstruktor versehen wird.

    Oder ich lasse durch den Anwendungsentwickler festlegen, welcher Wert in
    den Elternkonstruktor wandern soll:

    TClass::TClass(int val) : TBaseClass(val)
    {
       //nix
    }
    

    ==> nur falls der zu übergebende Parameter durch TClass festgesetzt werden soll,
    der Anwendungsentwickler demzufolge keinen Einfluss auf den Wert besitzt, und
    sich der Parameter nur mit einem vielleicht recht aufwändigen Algorithmus ermitteln lässt, nützen mir die oben genannten Ansätze natürlich nichts mehr!

    Eine Lösung wäre, wie ich jetzt weiss, ja z.B. folgendes:

    TClass::TClass() : TBaseClass(computeParam())
    
    <param> TClass::computeParam()
    {
      //hier: Parameter berechnen
      return(<param> );
    }
    

    Ist, aus meiner Sicht, natürlich etwas umständlich, für den Konstruktorenaufruf
    eigene Methoden zu entwickeln. Darum kam ich zu dem Irrglauben, dass das Problem
    auch folgendermaßen gelöst werden könnte:

    TClass::TClass() //zuerst Standardkonstruktor von TBaseClass, der nichts macht
    {
       //hier: Parameter berechnen
       TBaseClass::TBaseClass(<param> );
    }
    

    Und exakt das war mein Problem!

    Grüße,
    TS++

    [ Dieser Beitrag wurde am 13.04.2003 um 14:14 Uhr von TS++ editiert. ]


Anmelden zum Antworten