const variablen verändern



  • hallo leute

    ich schreibe hier gerade eine klasse die 2 const member hat

    bei dem einen konstruktor werden diese beiden als parameter direkt übergeben und dann per initialisierungs liste gesetzt

    bei dem anderen Ctor allerdings werden diese beiden werte erst aus einer datei gelesen...

    problem also: VC++ meckert dass man die beiden const member nicht per initliste initialisiert und danach kann ich sie ja nicht mehr ändern

    mein ansatz:
    entweder per schmutzigem trick das const ind em fall umgehen
    oder (aber ich glaube nicht dass es klappt) man erzeugt ein temporäres objekt dieser klasse mit den ausgelesenen werten und belegt das eigendliche objekt mit dem temp objekt
    da wäre noch zu zusagen dass es keinen copy Ctor und keine zuweisungsoperator gibt weil es für das anwendungs gebiet etwas schwachsinnig ist 😉

    was kann ich machen?
    und wie?



  • Warum nicht einfach const in die Tonne treten und den Zugriff von außerhalb durch einen Getter kapseln?



  • na ja mit "schmutzigen Tricks" geht das schon, aber eigentlich ist eine Konstante dazu da, dass sie eben nicht geändert wird, daher frage ich mich, ob du nicht irgendwo nen Designfehler hast ;).



  • Hmmmm, kann man nicht Konstanten über Rückgabewerte von Funktionen initialisieren ?
    Dann bräuchte es bloß eine entsprechende Funktion, die die Werte aus einer Datei einliest (sollte natürlich keine virtuelle Funktion der Klasse selbst sein, weil die zur Konstruktionszeit noch nicht definiert ist)...

    Oder täusche ich mich da?

    Nachtrag: Also bei mir (xlC V5) läuft das hier

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    string get(string const& s) {
       ifstream in(s.c_str());
       string ret;
       in >> ret;
       return ret;
    }
    
    struct A {
       string const s;
       A() : s("default") {}
       A(string const& in)  : s(get(in)) {}
    };
    
    int main() {
       A a1;
       A a2("main.cpp");
       cout << "a1: " << a1.s << "\n";
       cout << "a2: " << a2.s << "\n";
       return 0;
    }
    

    ...und ich wüsste auch nicht, was dagegen spräche - weder sprach- noch designtechnisch.
    Dass "const" nur für die Lebenszeit von Objekten gilt, ist ja nicht neu ... sonst wären ja auch const-Funktionsparameter (oder const lokale Variablen) nicht erlaubt.

    Gruß,

    Simon2.



  • Ich versteh jetzt nicht wieso du das const nicht einfach weglassen kannst. Wenn du es nunmal dringend ändern willst dann mach es auch änderbar. Andernfalls mach die Variable private und stell nur eine Getter Methode zur Verfügung. Das sollte doch auch reichen



  • Er will die const variable ja gar nicht ändern nur auf zwei unterschiedliche Arten initialisieren.
    Also ist die Lösung von Simon2 angenommen.



  • ok cool danke

    klappt so

    mh hätte ich eigendlich selbst drauf kommen können -.-


  • Administrator

    Wenn ich noch was dazufügen darf. Das Problem kommt meiner Meinung nach vor allem von einem Design-/Denkfehler. Ist es denn die Aufgabe dieser Klasse, dass sie ein File öffnen und interpretieren soll? Ich denke eher nicht.
    Korrekt wäre somit, dass du eine freie Funktion oder eine "Reader"-Klasse schreibst, welche die Datei einliesst und dann ein entsprechendes Objekt erstellt. Dem Konstruktor also gleich den Wert übergibt, welcher in der Initialisierungsliste gesetzt werden muss.

    Also grundsätzlich macht dein Konstruktor Dinge, welcher er gar nicht tun sollte, bzw. nicht in seinen Aufgabenbereich gehört.

    Grüssli



  • Dravere schrieb:

    ...Das Problem kommt meiner Meinung nach vor allem von einem Design-/Denkfehler. ...

    Naja ... so ganz pauschal würde ich das nicht sehen. Es kann IMHO durchaus in Ordnung sein (designtechnisch), wenn const-Member auch über komplexere Wege initialisiert werden können als einfache Wertübergabe per Ctor ... und auch, wenn diese Wege, die scheitern können.
    Das bedeutet aber nicht, dass diese Aufgabe automatisch die komplette "Erzeugungsverantwortung" für die Fachklasse haben muss.

    Gruß,

    Simon2.



  • falls es euch interessiert

    ich schreibe ein snake spiel (bzw es ist eig soweit fertig) und einmal soll man die grösse per Ctor angeben können um in einem rechteck ohne alles spielen zu können

    und einmal soll man einen dateinamen angeben können. in dieser datei sind dann levelkoordinaten gespeichert

    das snake spiel ist in einer klasse (weswegen ein copy Ctor und ein zuweiser blöd sind) und die breite und höhe ist als const unsigned int angegeben und die sollen halt aus der datei gelesen werden

    so wie simon2 es erklärt hat klappts auch gut

    ok ich muss zugeben es ist nicht gut designt aber das ist meine rstes spiel und mein erstes richtig projekt mit klassen


  • Administrator

    @Simon2,
    Sobald die Klasse komplexere Wege gehen muss, welche durch Regionen führen, welche sie nicht betrifft, dann gehört sowas ausgelagert. Der Konstruktor soll nur die eigenen Variablen initialisiseren. Die komplexen Wege sollten vorher getätigt werden.
    Ich denke das darf man durchaus so pauschal sagen, wie auch beim dynamic_cast . Kann sein, dass es Ausnahmen gibt, aber meistens ist das schon korrekt. Und meiner Meinung nach, ist es erst recht hier der Fall.

    @Skym0sh0,
    Vielleicht nur zwei Dinge (von womöglich vielen :)):
    1. Ich würde ein LevelLoader oder sowas ausserhalb der Klasse schreiben. Sowas gehört meiner Meinung nach ausgelagert.
    2. Es ist fraglich, ob diese Grössen wirklich const sein sollten. Man sollte es mit const auch nicht übertreiben 😉
    Kann es wirklich nicht sein, dass sich diese Grössen verändern? Wäre doch durchaus möglich, vielleicht sogar als Spielfeature 😉

    Grüssli



  • Dravere schrieb:

    @Simon2,
    Sobald die Klasse komplexere Wege gehen muss, welche durch Regionen führen, welche sie nicht betrifft, dann gehört sowas ausgelagert. Der Konstruktor soll nur die eigenen Variablen initialisiseren. Die komplexen Wege sollten vorher getätigt werden.
    Ich denke das darf man durchaus so pauschal sagen, wie auch beim dynamic_cast . ...

    Gerne.
    Ich war ja auch nicht gegen das Auslagern (mache ich in meinem Beispiel ja auch), sondern nur gegen die "Erzeugungsverantwortung".
    In diesem Fall, bei dem es letztlich nur um eine Datenquelle handelt, reicht IMHO die lockere Kopplung (get() hat einen eigentständigen Sinn und ist nicht nur zur Erzeugung von A da) vollkommen aus.
    Sobald die "äußere" Funktionalität aber noch für die Lebenszeit des Objekts Relevanz hat (z.B. wenn in unserem Beispiel eine Änderung in der Datei auch den Zustand eines erzeugten A-Objektes bewirken soll), fände ich eine engere Kopplung auch besser. ... aber als reine Datenquelle geht das schon in Ordnung.

    Leicht OT: Ich denke, es gibt hier 2 (gleich korrekte) Vorstellungen von "pauschal":
    a) Die Aussage trifft in den meisten/wesentlichen Fällen zu. Der Rest sind "Die Regel bestätigende Ausnahmen".
    b) Die Aussage trifft genau IMMER zu.
    Vermutlich meintest Du eher "pauschal-a)" während ich "pauschal-b)" meinte. 😉

    Gruß,

    Simon2.


Anmelden zum Antworten