Verleitet C++ zum komplizierteren denken?



  • volkard schrieb:

    Das (void) da ist sehr ungewöhnlich. Das war mal in C nötig, weil () beliebig viele Argumente akzeptierte (Ich hoffe, daß es inzwischen auch in C repariert worden ist.).

    Nein, noch gibt es MISRA Regeln und diese schreiben es so vor. Finde ich gut. Genauso wie ein return; bei void Funktionen:

    void func(void)
    {
        ...
        return;
    }
    

    Aber sagt MISRA einem PC Programmierer überhaupt was? 🙂
    Nur aus Neugier, benutzt jemand (freiwillig 😉 oder weil er muss) in seinen Projekten irgendwelche QAC/QAC++ Checker?



  • abc.w schrieb:

    Aber sagt MISRA einem PC Programmierer überhaupt was? 🙂

    mir sagt MISRA schon was. der zwang zu (void) ist eine typische heldentat solcher kommitees. mein beileid. naja, es verursacht ja keinen schaden und wenns in dieser branche alle tun, kann man sich leicht dran gewönen. das return; kann ich mir für C noch vorstellen, ist bei C++ aber sehr seltsam - gilt das auch für C++?



  • dünn besetztes Matrix-Vektor-Produkt:

    V1 := Dictionary new.
    V2 := Dictionary new.
    
    V1 at: 1 put: 3; at: 3 put: 1; at: 4 put: 4.
    V2 at: 1 put: 2; at: 4 put: 11.
    
    M := Dictionary new.
    M at: 1 put: V1; at: 3 put: V2.
    
    W := Dictionary new.
    W at: 1 put: 1; at: 3 put: 1.
    
    X := Dictionary new.
    
    M keys do: [ :i | 
    		d := (M at: i) dotProduct: W. 
    		(d = 0) ifFalse: [ X at: i put: d ]
    		].
    
    "X = M * W               "
    "    | 3 0 1  4 |   | 1 |"
    "  = | 0 0 0  0 | x | 0 |"
    "    | 2 0 0 11 |   | 1 |"
    "                   | 0 |"
    


  • u_ser-l schrieb:

    dünn besetztes Matrix-Vektor-Produkt:

    V1 := Dictionary new.
    V2 := Dictionary new.
    
    V1 at: 1 put: 3; at: 3 put: 1; at: 4 put: 4.
    V2 at: 1 put: 2; at: 4 put: 11.
    
    M := Dictionary new.
    M at: 1 put: V1; at: 3 put: V2.
    
    W := Dictionary new.
    W at: 1 put: 1; at: 3 put: 1.
    
    X := Dictionary new.
    
    M keys do: [ :i | 
    		d := (M at: i) dotProduct: W. 
    		(d = 0) ifFalse: [ X at: i put: d ]
    		].
    
    "X = M * W               "
    "    | 3 0 1  4 |   | 1 |"
    "  = | 0 0 0  0 | x | 0 |"
    "    | 2 0 0 11 |   | 1 |"
    "                   | 0 |"
    

    Wieder ein Versuch, mich zu veralbern. Aber der ist doch längst schon vorweggenommen.

    u_ser-l schrieb:

    volkard schrieb:

    volkard schrieb:
    Die Hashtable ist natürlich nicht ein Array von Zeilen-Hashtables, sondern Zeilen- und Spaltenindex werden zum hashkey kombiniert.

    das ändert am Prinzip gar nichts.

    Anscheinend doch.

    Lies auch double dispatching in smalltalk:
    http://www.mimuw.edu.pl/~sl/teaching/00_01/Delfin_EC/Patterns/DoubleDispatch.htm


  • Administrator

    abc.w schrieb:

    Aber sagt MISRA einem PC Programmierer überhaupt was? 🙂

    MISRA erinnert mich an "miserabel" 😃
    Aber das ist doch so ein Fahrzeug/Auto C Standard, oder? Irgendwo mal gehört, war glaub ich in irgendeiner Vorlesung.

    Grüssli



  • u_ser-l schrieb:

    dünn besetztes Matrix-Vektor-Produkt:

    V1 := Dictionary new.
    V2 := Dictionary new.
    
    V1 at: 1 put: 3; at: 3 put: 1; at: 4 put: 4.
    V2 at: 1 put: 2; at: 4 put: 11.
    
    M := Dictionary new.
    M at: 1 put: V1; at: 3 put: V2.
    
    W := Dictionary new.
    W at: 1 put: 1; at: 3 put: 1.
    
    X := Dictionary new.
    
    M keys do: [ :i | 
    		d := (M at: i) dotProduct: W. 
    		(d = 0) ifFalse: [ X at: i put: d ]
    		].
    
    "X = M * W               "
    "    | 3 0 1  4 |   | 1 |"
    "  = | 0 0 0  0 | x | 0 |"
    "    | 2 0 0 11 |   | 1 |"
    "                   | 0 |"
    

    Ich frag mich gerade, was an diese Struktur objektprogrammiert sein soll o_O vielleicht liegt es ja nur an meine nicht vorhanden Wissen über Smalltalk.



  • volkard schrieb:

    das return; kann ich mir für C noch vorstellen, ist bei C++ aber extrem schwachsinnig - gilt das auch für C++?

    Habe gerade die Meldungen eines QAC++ Checker durchsucht, keine passende Regel gefunden, wahrscheinlich doch schwachsinnig für C++...

    Dravere schrieb:

    Aber das ist doch so ein Fahrzeug/Auto C Standard, oder?

    Ja, so ungefähr, eher eine Zusammenstellung von Regeln. MISRA ist halb so schlimm, schlimm sind die Mitarbeiter (Vorgesetzten) die die Regeln für ein Projekt zusammenstellen 😉



  • abc.w schrieb:

    volkard schrieb:

    das return; kann ich mir für C noch vorstellen, ist bei C++ aber extrem schwachsinnig - gilt das auch für C++?

    Habe gerade die Meldungen eines QAC++ Checker durchsucht, keine passende Regel gefunden, wahrscheinlich doch schwachsinnig für C++...

    Na, sauber. Ich nehme an, für C unterstützt dieser Zwang das Single-Exit-Konzept, was Ressourcenlöcher vermeidet. Man hat irgendwie Lust, das return da unten zu bevorzugen, wo es doch eh schon da steht. 😋



  • um das dispatching Argument zu widerlegen, paßt es. Smalltalk rocks.



  • abc.w schrieb:

    ...noch gibt es MISRA Regeln und diese schreiben es so vor. Finde ich gut. Genauso wie ein return; bei void Funktionen:

    das 'void' schreibe ich in C auch immer hin. mir fällts sogar auf, wenn's fehlt. aber ein return am ende einer void-funktion ist doch blöd. was soll das?

    abc.w schrieb:

    Aber sagt MISRA einem PC Programmierer überhaupt was?

    bestimmt nicht. pc-progger haben echt glück, dass sie sich damit nicht belasten müssen. aber es gibt sicherlich noch viele andere furchtbare coding-richtlinien (hab mal was vom rüstungskonzern lockhheed für c++ gesehen). machmal ist sowas ja auch sinnvoll, denn schliesslich sind nicht alle programmierer so schlau wie volkard. und wenn irgendwo c++ in grossen projekten verwendet wird, geht's auch garnicht ohne sehr restriktive coding-styles, sonst kommen nur kraut und rüben raus.

    abc.w schrieb:

    Nur aus Neugier, benutzt jemand (freiwillig oder weil er muss) in seinen Projekten irgendwelche QAC/QAC++ Checker?

    ich hab diverse toolchains die auch 'nen misra-checker drin haben, den lass ich zum spass mal durchlaufen um mir hunderte von regelverstössen vorwerfen zu lassen. ne, aber im ernst: ich benutze ziemlich oft das: http://www.splint.org/ das ist richtig gut.
    🙂



  • u_ser-l schrieb:

    Smalltalk rocks.

    so toll smalltalk auch sein mag, aber ich finde die syntax absolut gruselig.
    🙂



  • /fricky schrieb:

    u_ser-l schrieb:

    Smalltalk rocks.

    so toll smalltalk auch sein mag, aber ich finde die syntax absolut gruselig.
    🙂

    Ich kann ihr einiges abgewinnen, weil sie so angenehm klein ist.



  • u_ser-l schrieb:

    um das dispatching Argument zu widerlegen, paßt es.

    Offensichtlich nicht.
    Nochmal was zum Lernen: http://dixie.cs.uiuc.edu/cs598rej/uploads/87/double-dispatch.pdf
    Deine Logik liegt in einer mir fremden Zonentaxonomie, fürchte ich.





  • ~john schrieb:

    Da wird nicht simuliert! Es ist echtes OOP! Einiges wird in C++ nicht direkt unterstützt, aber das trifft etwa auch auf Smalltalk zu.

    Hier wird z.B. das OO-Prinzip "Datenkapselung" nicht unterstützt:

    #include<iostream>
    
    using namespace std;
    
    class A {
    private:
        char c;
    public:
        A() { c = 'a'; }
        char* get() { return &c; }
    };
    
    int main(){
        A a;
    
        cout << "private a.c ist '" << *a.get() << "'" << endl;
        *a.get() = 'b';
        cout << "und jetzt: '" << *a.get() << "'" << endl;
    }
    
    der Kompeiler
    g++ -Wall
    

    spuckt bei mir übrigens nicht einmal eine warning aus, obwohl im Manual zu lesen ist:
    (Zitat)

    -Wall
    This enables all the warnings about constructions that some users consider questionable, [...]
    

    - es ist demzufolge not questionable, private members eines Objektes unbefugt von außen zu ändern :p



  • und hier kann ich die private Innerei des Objekts b der Klasse B manipulieren, indem ich einen Zeiger benutze, der vom Objekt a der Klasse A stammt - das könnte allerdings plattform- oder implementationsabhängig sein:

    #include<iostream>
    
    using namespace std;
    
    class A {
    private:
        char c;
    public:
        A() { c = 'a'; }
        char* get() { return &c; }
    };
    
    class B {
    private:
        char c;
    public:
        B() { c = 'b'; }
        char get() { return c; }
    };
    
    int main(){
        B b;
        A a;
    
        cout << "private b.c ist '" << b.get() << "'" << endl;
        *(a.get() + 1) = 'x';
        cout << "und jetzt: '" << b.get() << "'" << endl;
    }
    

    Ausgabe bei mir:

    private b.c ist 'b'
    und jetzt: 'x'
    


  • u_ser-l schrieb:

    - es ist demzufolge not questionable, private members eines Objektes unbefugt von außen zu ändern :p

    Es gibt Tools zur statischen Analyse des Quellcodes und Fehler dieser Art (ich nenne sie jetzt einfach mal Fehler, obwohl der Compiler nicht mal eine Warnung ausspuckt) würden sofort auffallen 🙂



  • u_ser-l schrieb:

    ~john schrieb:

    Da wird nicht simuliert! Es ist echtes OOP! Einiges wird in C++ nicht direkt unterstützt, aber das trifft etwa auch auf Smalltalk zu.

    Hier wird z.B. das OO-Prinzip "Datenkapselung" nicht unterstützt:

    #include<iostream>
    
    using namespace std;
    
    class A {
    private:
        char c;
    public:
        A() { c = 'a'; }
        char* get() { return &c; }
    };
    
    int main(){
        A a;
    
        cout << "private a.c ist '" << *a.get() << "'" << endl;
        *a.get() = 'b';
        cout << "und jetzt: '" << *a.get() << "'" << endl;
    }
    

    Es wird gekapselt, aber was anderes, naemlich der Pointer (die Adresse) und nicht der Wert auf den der Pointer zeigt. Wuerde sowas z.B. funktionieren, dann wuerde die Kapselung verletzt werden:

    a.get() = 0xFF00FF; // irgendeine Adresse
    

    In C++ gibt es aber trotzdem keine Kapselung im OOP-Stil, weil alle private member der Klasse oeffentlich bekannt sind und jede Aenderung an den private members eine Aenderung des Client-Codes noetig macht (man muss den Client-Code neu uebersetzen).



  • und hier ein Objekt, auf das man nach Zerstörung munter zugreifen kann:

    #include<iostream>
    
    using namespace std;
    
    class A {
    private:
        char *s; 
    public:
        A() { s = (char*)"bin noch da!"; }
        ~A() { cout << "Destruktor (und weg)" << endl; }
        char *get() { return s; }
    };
    
    int main(){
        A a;
    
        a.~A();
    
        cout << a.get() << endl;
    
        a.~A();
    
        cout << a.get() << endl;
    }
    

    Ausgabe bei mir:

    Destruktor (und weg)
    bin noch da!
    Destruktor (und weg)
    bin noch da!
    Destruktor (und weg)
    

    und auch keine warning bei g++ -Wall ...

    echte OOP oder namespace feature ?



  • Offen gesagt sehe ich nicht den Zusammenhang zwischen den zweifelsohne zahllosen Fällen, in denen C++ groben Unfug zu betreiben erleichtert oder überhaupt erst ermöglicht, und der objektorientierten Programmierung.

    Davon abgesehen sind deine Beispiele unsinnig. Wenn du ein Element hättest kapseln wollen, hättest du einen const-Verweis zurückgegeben. Und der zweite Fall ist einfach falsch - worauf dich z.B. CodeGuard hingewiesen hätte. Es hindert dich ja auch in Java oder C# niemand daran, dispose() mehrfach oder finalize() explizit aufzurufen.


Anmelden zum Antworten