10 C++ Testfragen



  • nonstop schrieb:

    List vs. Vector hat nichts mit Standardbibliothek zu tun sondern mit Datenstrukturen allgemein.

    Trotzdem arbeitet die STL mit eher C++-spezifischen Konzepten wie Iteratoren, Zeiger und Templates. Und meiner Ansicht nach tragen die STL-Container auch zum Verständnis der Sprache C++ bei - zumindest würde ich von niemanden sagen, er kenne sich mit C++ aus, wenn er noch nichts von der STL (oder allgemein Standardbibliothek) gehört hat.

    nonstop schrieb:

    dynamic_cast macht man in anderen Sprachen mit instanceof usw.

    Hm, instanceof kenne ich jetzt nicht, aber ich glaube nicht, dass das genau identisch mit dynamic_cast ist. Oder warum meinst du?

    nonstop schrieb:

    Oder was stellst du dir bei denen für ne Antwort vor die nur für C++ zutrifft?

    Wieso darf die Antwort nur auf C++ zutreffen? Es geht ja darum, wie gut man C++ beherrscht. Sehr viele Dinge, die man in C++ lernt, kann man dann auch in anderen Sprachen besser anwenden. Das fängt schon bei grundlegendsten Dingen wie If-Abfragen und Schleifen an und zieht sich über sehr viele Sprachkonzepte hinweg.

    nonstop schrieb:

    Pattern dürfte wohl klar sein, das es allgemein ist.

    Da stimme ich dir schon eher zu. Aber ich finde, man erhält so auch Auskunft darüber, wie gut man eine Programmiersprache wie C++ in der Praxis anwenden kann. C++ geht gegenüber anderen modernen Sprachen wie C# oder Java ein wenig seinen eigenen Weg, was Objektorientierung betrifft. Das dürfte bereits einen Unterschied bezüglich Entwurfsmuster bewirken. Zudem kommen dann auch noch andere Differenzen wie Zeiger dazu, was wiederum einen Teil beiträgt.

    Die ursprüngliche Fragestellung lässt einem sowieso sehr viel Spielraum - man kann die Kenntnis der Sprache C++ nicht ausschliesslich an den Sprachmitteln messen, die in anderen Programmiersprachen nicht vorkommen.

    Tut mir übrigens leid, dass ich dir deinen Post so zerstückelt habe, aber ich wollte halt spezifisch antworten. 😉



  • Nexus schrieb:

    nonstop schrieb:

    Oder was stellst du dir bei denen für ne Antwort vor die nur für C++ zutrifft?

    Wieso darf die Antwort nur auf C++ zutreffen? Es geht ja darum, wie gut man C++ beherrscht. Sehr viele Dinge, die man in C++ lernt, kann man dann auch in anderen Sprachen besser anwenden. Das fängt schon bei grundlegendsten Dingen wie If-Abfragen und Schleifen an und zieht sich über sehr viele Sprachkonzepte hinweg.

    Sag ich doch. Hat jetzt nicht wirklich was mit C++ zu tun sondern mit SW-Entwicklung allgemein.



  • nonstop schrieb:

    Sag ich doch. Hat jetzt nicht wirklich was mit C++ zu tun sondern mit SW-Entwicklung allgemein.

    Du hast nicht verstanden, was ich sagen wollte. Ich behaupte, dass sich jenes von dir genannte Kriterium sich auf die meisten Sprachmittel von C++ anwenden lässt.

    Nochmals:

    Nexus schrieb:

    man kann die Kenntnis der Sprache C++ nicht ausschliesslich an den Sprachmitteln messen, die in anderen Programmiersprachen nicht vorkommen.

    In diesem Kontext wäre die ursprüngliche Fragestellung des Threaderstellers also sinnlos.



  • Virokams schrieb:

    3. warum kann einem const char * nichts zugewiesen werden. 😕

    Die Frage ist falsch gestellt. Es geht nämlich, der Zeiger ist nicht "const".



  • nonstop schrieb:

    dynamic_cast macht man in anderen Sprachen mit instanceof usw.

    Und seltsamerweise deutet die Benutzung von "instanceof" usw. in anderen Sprachen nicht auf Designfehler hin.



  • ~john schrieb:

    Virokams schrieb:

    3. warum kann einem const char * nichts zugewiesen werden. 😕

    Die Frage ist falsch gestellt. Es geht nämlich, der Zeiger ist nicht "const".

    Besser wäre:
    Warum kann ein char** nicht einem const char** zugewiesen werden? 😉



  • 7H3 N4C3R schrieb:

    Besser wäre:
    Warum kann ein char** nicht einem const char** zugewiesen werden?

    Auch nicht gut. Es geht so: a = (const char**)b;



  • c++fan 2008 schrieb:

    7H3 N4C3R schrieb:

    Besser wäre:
    Warum kann ein char** nicht einem const char** zugewiesen werden?

    Auch nicht gut. Es geht so: a = (const char**)b;

    Das ist aus der Rubrik, warum man C-Casts nicht verwenden sollte.



  • c++fan 2008 schrieb:

    7H3 N4C3R schrieb:

    Besser wäre:
    Warum kann ein char** nicht einem const char** zugewiesen werden?

    Auch nicht gut. Es geht so: a = (const char**)b;

    Legt nahe, dass du die Frage bzw. das Problem nicht verstanden hast 😉



  • ~john schrieb:

    Das ist aus der Rubrik, warum man C-Casts nicht verwenden sollte.

    Was man soll oder nicht soll ist nicht relevant. Fakt ist: es geht.

    7H3 N4C3R schrieb:

    c++fan 2008 schrieb:

    7H3 N4C3R schrieb:

    Besser wäre:
    Warum kann ein char** nicht einem const char** zugewiesen werden?

    Auch nicht gut. Es geht so: a = (const char**)b;

    Legt nahe, dass du die Frage bzw. das Problem nicht verstanden hast

    Nein, es liegt an der unpräzisen Fragestellung.



  • Fang den Fisch: <°>>><



  • c++fan 2008 schrieb:

    nonstop schrieb:

    dynamic_cast macht man in anderen Sprachen mit instanceof usw.

    Und seltsamerweise deutet die Benutzung von "instanceof" usw. in anderen Sprachen nicht auf Designfehler hin.

    Doch, sofern wir mit dem "Designfehler" das gleiche meinen, nämlich die Tatsache, dass wir einen Typen nicht universell genug behandeln.



  • Nexus schrieb:

    nonstop schrieb:

    Sag ich doch. Hat jetzt nicht wirklich was mit C++ zu tun sondern mit SW-Entwicklung allgemein.

    Du hast nicht verstanden, was ich sagen wollte. Ich behaupte, dass sich jenes von dir genannte Kriterium sich auf die meisten Sprachmittel von C++ anwenden lässt.

    Nochmals:

    Nexus schrieb:

    man kann die Kenntnis der Sprache C++ nicht ausschliesslich an den Sprachmitteln messen, die in anderen Programmiersprachen nicht vorkommen.

    In diesem Kontext wäre die ursprüngliche Fragestellung des Threaderstellers also sinnlos.

    Ich hab schon verstanden was du willst, aber man kann schon zwischen Fragen speziel über C++ (z.B Initialisierungsliste, Idioms(Safe bool...) ) und Fragen über SW-Entwicklung (List<>Vector, Pattern) die auch ein Javaentwickler beantworten kann unterscheiden.



  • Designer! schrieb:

    c++fan 2008 schrieb:

    nonstop schrieb:

    dynamic_cast macht man in anderen Sprachen mit instanceof usw.

    Und seltsamerweise deutet die Benutzung von "instanceof" usw. in anderen Sprachen nicht auf Designfehler hin.

    Doch, sofern wir mit dem "Designfehler" das gleiche meinen, nämlich die Tatsache, dass wir einen Typen nicht universell genug behandeln.

    Nimm an, du schreibst ein Vektorgrafikprogramm. Alle Grafikobjekte sind von einer Basisklasse abgeleitet, nennen wir sie mal "GraphicsObject", die nur grundlegende Funktionalität implementiert, wie z.B. "setVisible". Wenn du nun das ganze Bild verwalten möchtest, zum Beispiel in einem Array oder einer Liste, dann ist es ganz praktisch, wenn du in der Containerklasse Pointer, Referenzen oder Kopien der Basisklasse speicherst. Für das nachträgliche Auseinanderklambüsern kannst du zum Beispiel dynamic_cast<> benutzen. Wo ist der Designfehler?



  • c++fan 2008 schrieb:

    Für das nachträgliche Auseinanderklambüsern kannst du zum Beispiel dynamic_cast<> benutzen.

    Wieso sollte man das auseinandernehmen? Durch virtuelle Methoden, die in der Basisklasse deklariert wurden, kann man für jedes Objekt die richtige Funktionalität erzielen.



  • SCNR vorab. 😃

    1. von 7N3 N43CR: Warum kann ein char** nicht einem const char** zugewiesen werden?

    2. Welche Schwachstellen fallen in folgender Methode auf, und wie sollte man sie am besten beheben?

    #include <cstdio>
    
    struct data_t
    {
        int     val1;
        int     val2;
        double  val3;
    
        void loadFromFile (const char* filename)
        {
            static const char* signature = "MYDATAFORMAT";
    
            std::FILE* file = std::fopen (filename, "rb");
            if (!file)
                throw "File not found (or so)";
    
            unsigned siglen = std::strlen (signature);
            char* sigbuf = new char[siglen];
            std::fread (sigbuf, std::strlen (signature), 1, file);
            if (std::strcmp (signature, sigbuf) != 0)
                throw "Unknown file format!";
    
            std::fread (this, sizeof (data_t), 1, file);
            std::fclose (file);
            delete sigbuf;
        }
    };
    

    3. von Nexus: Worin bestehen die Vorteile von std::list gegenüber std::vector? Zähle drei wesentliche auf. (Allerdings wäre es vielleicht besser, einen begründeten, aber wertungslosen Vergleich zu fordern.)

    4. Was genau bewirkt diese Anweisung?

    ((void(*)())0)();
    

    5. Was passiert, wenn dieses Programm ausgeführt wird?

    #include <iostream>
    
    struct Base;
    
    void printClassName (const Base* obj);
    
    struct Base
    {
        virtual const char* getClassName (void) const = 0; // abstrakte Basisklasse
        Base (void) { printClassName (this); }
        virtual ~Base (void) { printClassName (this); }
    };
    
    void printClassName (const Base* obj)
    { std::cout << "This is a '" << obj->getClassName () << "'" << std::endl; }
    
    struct Derived : Base
    {
        virtual const char* getClassName (void) const { return "Derived"; }
    };
    
    int main (void)
    {
        Derived d;
        Base* b = &d;
        std::cout << "This is a " << b->getClassName () << std::endl;
    }
    

    6. Konvertieren Sie diese Zeile in intuitiv lesbaren Code.

    int (*foo (bool)) (char);
    

    Das ist ungefähr aufsteigend nach Schwierigkeitsgrad sortiert und reicht fürs erste.

    Edit: Untenstehender Anmerkung von Phoemuex entsprechend Frage Nr. 5 angepaßt.
    Für 7.-10. wären wahrscheinlich ein paar template-bezogene Fragen sinnvoll.



  • audacia schrieb:

    (Allerdings wäre es vielleicht besser, einen begründeten, aber wertungslosen Vergleich zu fordern.)

    Hab ich mir auch überlegt, aber dann würde vielleicht vielen nur ein Argument einfallen. Man kann schliesslich auch 3 Vorteile nennen und begründen. 😉

    Aber ich finde deine Liste recht gut, zum Teile habe ich auch Mühe damit. 🙂



  • audacia schrieb:

    5. Was passiert, wenn dieses Programm ausgeführt wird?

    #include <iostream>
    
    struct Base
    {
        virtual const char* getClassName (void) = 0; // abstrakte Basisklasse
        Base (void) { std::cout << "Constructing a '" << getClassName () << "' object" << std::endl; }
        virtual ~Base (void) { std::cout << "Destroying a '" << getClassName () << "' object" << std::endl; }
    };
    
    struct Derived : Base
    {
        virtual const char* getClassName (void) { return "Derived"; }
    };
    
    int main (void)
    {
        Derived d;
        Base* b = &d;
        std::cout << "This is a " << b->getClassName () << std::endl;
    }
    

    Nichts, denn (mit einem vernünftigen Compiler) linkt es erst gar nicht.

    Felix



  • Phoemuex schrieb:

    Nichts, denn (mit einem vernünftigen Compiler) linkt es erst gar nicht.

    Aah, richtig.
    Also eine kleine Indirektion mehr, und schon geht es. Ich trage es oben nach.



  • audacia schrieb:

    2. Welche Schwachstellen fallen in folgender Methode auf, und wie sollte man sie am besten beheben?

    #include <cstdio>
    
    struct data_t
    {
        int     val1;
        int     val2;
        double  val3;
    
        void loadFromFile (const char* filename)
        {
            static const char* signature = "MYDATAFORMAT";
    
            std::FILE* file = std::fopen (filename, "rb");
            if (!file)
                throw "File not found (or so)";
    
            unsigned siglen = std::strlen (signature);
            char* sigbuf = new char[siglen];
            std::fread (sigbuf, std::strlen (signature), 1, file);
            if (std::strcmp (signature, sigbuf) != 0)
                throw "Unknown file format!";
    
            std::fread (this, sizeof (data_t), 1, file);
            std::fclose (file);
            delete sigbuf;
        }
    };
    

    Alles neu schreiben.


Anmelden zum Antworten