Zuständigkeitsketten/vererbungsproblem



  • drakon schrieb:

    Habe jetzt nicht alles gelesen, aber Iteratoren unterstzützen normalerweise den *-Operator:

    (*iter).query
    

    wie waere es mit

    iter->query
    

    ?



  • Shade Of Mine schrieb:

    drakon schrieb:

    Habe jetzt nicht alles gelesen, aber Iteratoren unterstzützen normalerweise den *-Operator:

    (*iter).query
    

    wie waere es mit

    iter->query
    

    ?

    Jo, wollte ich auch noch schreiben, musste aber gerade weg. 😉



  • Shade Of Mine schrieb:

    wie waere es mit

    iter->query
    

    ?

    habs versucht:

    bool ChainOfResponsibility::request( std::string& test )
    {
    	std::list<obj*>::iterator iter;
    	for( iter = chain.begin(); iter != chain.end(); iter++ )
    	{
    		iter->query( "bla" );
    		if( iter->getQuery() == test ) return true;
    	}
    	return false;
    }
    

    Fehler:

    g++ TESTAPP.cpp -o TESTAPP
    TESTAPP.cpp: In member function ‘bool ChainOfResponsibility::request(std::string&)’:
    TESTAPP.cpp:63: error: request for member ‘query’ in ‘* iter.std::_List_iterator<_Tp>::operator-> [with _Tp = obj*]()’, which is of non-class type ‘obj*’
    TESTAPP.cpp:64: error: request for member ‘getQuery’ in ‘* iter.std::_List_iterator<_Tp>::operator-> [with _Tp = obj*]()’, which is of non-class type ‘obj*’
    

    mfg



  • iter zeigt ja selbst auf einen Zeiger. Du musst den Iterator also zweimal dereferenzieren:

    (*iter)->query
    

    oder:

    (**iter).query
    


  • Auma schrieb:

    ...habs versucht:

    ...
    {
    	std::list<obj*>::iterator iter;
    ...
    

    Naja, kleiner Denkfehler von Dir:

    • ein Iterator zeigt auf ein Listenelement. Deswegen kann man mit '->' bzw. '*' auf ein Listenelement zugreifen.
    • in Deiner Liste verwaltest Du aber Zeiger auf Objekte. Willst Du also von einem Listenelement auf das dahinterliegende Objekt zugreifen, brauchst Du wiederum '->' bzw. '*'

    Ein Hinwis darauf findet sich tatsächlich in der Fehlermeldung:

    Auma schrieb:

    ...

    ...List_iterator<_Tp>::operator-> [with _Tp = obj*]()’, which is of non-class type ‘obj*’...
    

    ...

    Hier brauchst Du also:

    (*iter)->query
    // iter = "Zeiger auf ein Listenelement"
    // (*iter) = Listenelement = obj*
    // (*iter)-> = obj
    

    Gruß,

    Simon2.



  • ja 😃 vielen dank jetzt Kompiliert es... leider kommt es zu einem Segmentation fault 😮
    Ich lass das ganze mal durch nen Debugger laufen 🙂 ...
    mfg



  • Auma schrieb:

    Ich lass das ganze mal durch nen Debugger laufen 🙂 ...
    mfg

    👍

    Gute Entscheidung.



  • Auma schrieb:

    ja 😃 vielen dank jetzt Kompiliert es... leider kommt es zu einem Segmentation fault 😮
    Ich lass das ganze mal durch nen Debugger laufen 🙂 ...
    mfg

    Dir ist hoffentlich der Fehler an dieser Stelle klar:

    ChainOfResponsibility::ChainOfResponsibility( obj* ObjA, obj* ObjB)
    {
        chain.push_back( ObjA );
        chain.push_back( ObjB );
    }
    
    int main()
    {
        A *a; // 1.
        B *b; // 1.
        ChainOfResponsibility Ch( a, b ); // 2.
        //...
    }
    

    Ansonsten: Zurück zu den Grundlagen...

    1. Uninitialisierte Zeiger sind böse
    2. Du kannst doch nicht erwarten das eben diese Zeiger in deiner Liste Sinn machen.

    Davon ganz abgesehen solltest du Tips immer ganz oder garnicht beherzigen:

    virtual std::string query( std::string& ) = 0;
    

    Soll query den Übergabestring ändern können? Wenn nein, bitte eine konstante Referenz verwenden (Schreibweise: "std::string const &" oder "const std::string &").

    Zudem trennt man Code in Deklaration und Definition (Header/Source) und es ist - ich wiederhole nochmal - eine Unsitte im Header die Bezeichner wegzulassen. Stell dir vor du schaust dir deinen Code nach einen halben Jahr nochmal an. Möchtest du für einen Kurzen Überblick wirklich genötigt werden die Implementierung durchzuarbeiten? Man sollte immer gegen die Schnittstelle (Header), nicht gegen die Implementierung programmieren, und daher sollte für das Verständnis der Header ausschlaggebend sein.

    class ChainOfResponsibility
    {
        //...
        bool request( std::string& );
        //...
    }
    

    Was soll diese Methode uns sagen? Ich kann daraus nur ablesen das irgendetwas angefordert wird. Der Bezeichner (da fehlend) gibt nichts her, und auch der Methodenname alleine hilft nicht dabei den Aufruf zu verstehen. Was ich noch ablesen kann ist, das die Methode einen String als Argument erhält, und dieser innerhalb der Methode manipuliert wird (Ansonsten würde ja eine konstante Referenz verwendet werden).

    Programme sollten so geschrieben werden das sie möglichst selbsterklärend sind. Wenn du deinen Code nach einen halben Jahr nochmal üerfliegst weißt du wovon ich spreche...

    cu André



  • ja, danke es funktioniert.

    asc schrieb:

    Uninitialisierte Zeiger sind böse

    keine Ahnung warum ich das übersehen hab 🙄

    asc schrieb:

    [...]bitte eine konstante Referenz verwenden[...]

    das Programm schrieb ich ja nur um das Prinzip besser zu verstehen, aber du hast recht wenn dann richtig 🙂
    Die Bezeichner spielen somit auch keine Rolle, ich werde das Programm/den Code sicher nicht lange aufbewahren.
    mfg



  • Auma schrieb:

    asc schrieb:

    [...]bitte eine konstante Referenz verwenden[...]

    das Programm schrieb ich ja nur um das Prinzip besser zu verstehen, aber du hast recht wenn dann richtig 🙂
    Die Bezeichner spielen somit auch keine Rolle, ich werde das Programm/den Code sicher nicht lange aufbewahren.

    Der Mensch ist ein Gewohnheitstier. Wenn du dir den Stil früh angewöhnst, wird du ihn auch durchziehen wenn du es wirklich benötigst. Zudem mag das Projekt ein "Wegwerfprojekt" sein, für die anderen Threadleser helfen Bezeichner aber durchaus weiter, selbst wenn du diese nicht benötigst ;)...

    cu André


Anmelden zum Antworten