Stack & const



  • Hallo Leute,

    ich möchte eine Stackimplementation aus Nicolai Josuttis "objektorientiertes Programmieren in C++" verwenden, um Events in einem Stack zu speichern (EventQueue). Die Events werden dabei durch Enumeration festgelegt – etwa in dieser Form:

    enum Glob_Events {Event1 = 0, Event2, Event3};
    enum StateMachiens {SM1 = 0, SM2, SM3};
    

    Bei Auftreten des Events, soll in einer struct der Event und dessen Destination abgespeichert werden:

    struct Events {
    unsigned const TheEvent;
    unsigned const TheMachine;
    //int EventAge;
    Events(unsigned const TheEvent, const unsigned TheMachine) : TheEvent(TheEvent), TheMachine(TheMachine)  {};
    Events() : TheEvent(0), TheMachine(0) {};
    };
    

    Natürlich dürfen und sollen sich die Events nach deren Entstehung nicht verändern, weswegen ich mich entschied, diese in der struct als const zu initialisieren. Wenn man diese struct in dem Stack mit einer push- artigen Aktion abspeichern will, stößt man allerdings wegen der const auf ein Problem:

    //push
    template <class T> void Stack<T>::push (T& x)
    {
    	//increase memory if required
    	if(size <= numElems) {
    		T* tmp = elems;
    		size *= 2;
    		elems = new T[size];
    
    		//copy eexciting elemnts into memory
    		for (int i=0; i<numElems; i++) {
    			elems[i] = tmp[i]; //const objects cannot be coppied…
    		}
    		delete [] tmp; //delete all! tmp's
    	}
    	elems[numElems++] = x;
    }
    

    Nun könnte man die Events auch einfach nur als "unsigned" in der (nicht const) struct abspeichern – aber kann ich mir sicher sein, dass der Event sich nicht verändert wird ?



  • Hi, müssen Konstanten nicht einen festen Wert haben, der sich nicht verändern lässt? Und muss nicht auch der Datentyp angegeben werden?
    LG



  • Hallo,

    ich habe jetzt einfach mal einen "=" eingebaut, womit es scheinbar geht - aber ist das sinnvoll ?

    struct Events {
    unsigned const TheEvent;
    unsigned const TheMachine;
    //int EventAge;
    Events(unsigned const TheEvent, const unsigned TheMachine) : TheEvent(TheEvent), TheMachine(TheMachine)  {};
    Events() : TheEvent(0), TheMachine(0) {};
    const Events &operator=(const Events *obj) { //edited: &obj -> *obj
        return *this;
      }
    };
    

    müssen Konstanten nicht einen festen Wert haben, der sich nicht verändern lässt? Und muss nicht auch der Datentyp angegeben werden?

    -> Ja, Konstanten sollen einen festen Wert haben
    -> Ich habe irgendwo mal gelesen, dass enum- typen vom Type "unsigned const" sind - keine Ahnung ob das stimmt.



  • Nein nein, rein syntaktisch ist das schon richtig, was Op da schreibt.

    Aber konzeptionell ist das suboptimal.
    Erstmal, wieso schreibst du einen Stack-Datenstruktur selbst? Wieso nutzt du nicht std::stack?

    In beiden Fällen müssen die Daten nämlich kopiert werden (oder wenigstens gemovet). Was std::stack da erfordert müsste ich nachschauen.

    Aber du kannst deine Events hinter einer Klasse wegkapseln und einfach keinen schreibenden Zugriff darauf geben, so dass sich die Events nicht ändern können von außen. Wenn die Interna deiner Klasse die ändern, dann hast du da die volle Kontrolle drüber und solltest das halt nicht machen, wenn dus nicht brauchst.

    Es ist oft eh keine gute Idee Datenmember von Klassen konstant zu machen, weil du damit die Kopierbarkeit angreifst:

    Foo a = ...;
    
    Foo c(a); // geht zu kopieren
    Foo b = a; // derselbe Konstruktor wie oben
    
    Foo a = Foo(...); // geht nicht mehr
    

    Über Klasseninterna hast du (allein) die volle Kontrolle, und viel öfters möchtest du dann Daten nicht ändern (indem du sie einfach nicht von aussen zugreifbar machst) oder der User macht dein ganzes Objekt direkt konstant.



  • Achja, und ich würde dir empfehlen enum classes zu verwenden. Und statt der unsigned Konstante eine Instanz von deinem enum...



  • Scheinbar funktioniert dies doch nicht so wie gedacht - und zwar liefert

    //push
    template <class T> void Stack<T>::push (T& x)
    {
    	//increase memory if required
    	if(size <= numElems) {
    		T* tmp = elems;
    		size *= 2;
    		elems = new T[size];
    
    		//copy eexciting elemnts into memory
    		for (int i=0; i<numElems; i++) {
    			printf("Copying \n");
    			elems[i] = tmp[i];
    
    		}
    		delete [] tmp; //delete all! tmp's
    	}	
    	//Argument
    	printf("%d  %d \n", ((Events) x).TheEvent, ((Events) x).TheMachine );
    	//geht
    	T* test = new T;
    	test = &x;
    	printf("%d  %d \n", ((Events) *test).TheEvent, ((Events)       
                                                             *test).TheMachine );
    	//geht nicht
    	numElems++;
    	elems[numElems] = x;
    	printf("%d  %d \n", ((Events) elems[numElems]).TheEvent, ((Events) elems[numElems]).TheMachine );
    }
    

    ..die Operation "elems[numElems] = x;" nur die default- Initialisiation der
    Events- struct, nämlich "0,0". Vermutlich liegt es am "=" operator in der struct - dieser funktioniert natürlich nur bei der Initialisierung etwa so:

    Events test = newEvent2; //geht
    test = newEvent2; /geht nicht

    (Aber das wollte mir sicher der Vorposter auch mit seinem Post sagen.)

    Da werde ich wohl auf const verzichten müssen...


Log in to reply