Verleitet C++ zum komplizierteren denken?



  • 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.



  • Ich finde nicht dass C++ zu komplizietem Denken vereleitet. Ich programmiere seit etwa 5 Jahren in C++. Das wäre mir aufgefallen



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

    es gibt einen Unterschied zwischen Unterstützen und Erzwingen.

    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).

    Diese Aussage trifft nicht wirklich zu, weil der Client Code nicht geändert wird, sondern nur das Resultat. Aber ist das wirklich gegen OOP?


Anmelden zum Antworten