Was fehlt in C++11?



  • Eieiei ;). Folgender Code als Beispiel:

    MemberInfo[] MyMemberInfoArray = GetType().GetProperties();
            for (int counter = 0; counter < MyMemberInfoArray.GetLength(0); counter++ )
            {
                String message = counter.ToString() + " / " + MyMemberInfoArray[counter].Name + " / " + MyMemberInfoArray[counter].MemberType.ToString();
                MessageBox.Show(message, "");
            }
    

    So kann ich mir in C# die Namen aller Properties einer Klasse zur Laufzeit ausgeben lassen. Mit "GetMembers" anstatt "GetProperties" die aller Funktionen usw. In C++ gehen all diese Informationen beim Compilieren verloren. Darum muss ich in C++ diese per Hand hinzufügen:

    namespace MyNamespace
    {
    
    class MyClass
    {
    public:
    static std::wstring klassenName;
    static std::wstring namespaceName;
    }
    
    std::wstring MyClass::klassenName = L"MyClass";
    std::wstring MyClass::namespaceName = L"MyNamespace";
    
    }
    

    Wenn ich die Klasse nun in einen weiteren Namespace packe oder den Namen der Klasse verändere dann stimmen die Namen in den statisch hinterlegten Strings nicht mehr. Das meinte ich mit Fehleranfällig. In C# sind all diese Informationen aber schon automatisch vorhanden. Jetzt verständlich?



  • Und wofür brauch ich die Informationen?



  • Das ist etwas völlig anderes, als ich vorhin verstanden habe. (und du vorhin IMHO auch behauptet hast) Aber jetzt ist es klar.



  • Ja das ist Reflection. Und das braucht man in C++ nicht 😉



  • Ich gebe es auf. Kein Wunder dass C++ am aussterben ist.



  • Ist es das? Ich glaub eher das Problem hier ist dass du C++ nicht verstanden hast 😉

    Ich hab bisher jedenfalls noch kein Problem gesehen zu dessen Lösung Reflection essentiell wäre. Und ich war bisher in Sprachen wo ich Reflection gehabt hätte (C#) im Nachhinein immer froh mich für die bessere Lösung ohne Reflection entschieden zu haben da das Programm am Ende dann flexibler war. Aber natürlich ist Reflection angenehm um schnell was hinzumachen, keine Frage...



  • Sorry wegen der Verwirrung, aber ich dachte RTTI und Reflection sind mehr oder weniger das selbe. Ich meine Runtime Type Information sagt doch genau das aus was Reflection macht.
    Klar, wenn man Microcontroller programmiert braucht man sowas nicht. Aber es soll auch noch andere Gebiete wie z.B. GUI-Programmierung geben wo mir Reflection extrem viel hilft.



  • RTTI und Reflection sind zwei verschiede Sachen.



  • StellerFragen schrieb:

    Sorry wegen der Verwirrung, aber ich dachte RTTI und Reflection sind mehr oder weniger das selbe. Ich meine Runtime Type Information sagt doch genau das aus was Reflection macht.

    Naja, ist es ja im Prinzip auch, RTTI ist eine Form von Reflection. Und du hast recht, C++ bietet da vergleichsweise extrem beschränkte Mittel. Und ich würd mir nicht wünschen dass es anders wär, ich hab Reflection noch nie vermisst.

    StellerFragen schrieb:

    Aber es soll auch noch andere Gebiete wie z.B. GUI-Programmierung geben wo mir Reflection extrem viel hilft.

    Wenn ich komplexe GUIs mach dann verwend ich dafür nicht C++ sondern C#. Aber auch in C# mach ich normalerweise einen Bogen um Reflection. Meiner Erfahrung nach resultiert das nur in unflexiblem Design, wenn auch doppelt so schnell 😉



  • StellerFragen schrieb:

    Ich meine Runtime Type Information sagt doch genau das aus was Reflection macht.

    Nein, RTTI heisst nur, dass ich den Typ eines Objekts zur Laufzeit bestimmen kann.

    StellerFragen schrieb:

    Klar, wenn man Microcontroller programmiert braucht man sowas nicht. Aber es soll auch noch andere Gebiete wie z.B. GUI-Programmierung geben wo mir Reflection extrem viel hilft.

    Reflection kann sicher ab und zu nützlich sein, aber teilweise wird es auch in Situationen eingesetzt, die man in C++ nicht hat oder bereits zur Kompilierzeit löst. Ich mag mich an einen Fall erinnern, in dem ich es hätte brauchen können. Und zwar zur Implementierung eines Double-Dispatchers, wo ich eine Derived-Base-Beziehung zur Laufzeit überprüfen wollte.

    Aber dass du C++ direkt mit Mikrokontrollern assoziierst, bestätigt nur dots These 😉



  • Nexus schrieb:

    Nein, RTTI heisst nur, dass ich den Typ eines Objekts zur Laufzeit bestimmen kann.

    Und inwiefern ist das nicht eine Form von Reflection!? Natürlich kann Reflection viel weiter gehen als das aber da fängts an wenn du mich fragst.



  • Das sehe ich auch so. Meiner Meinung nach unterscheiden C++ler zwischen RTTI und Reflection nur weil ersteres nicht das Gleiche bieten kann.



  • Ja C++ bietet nur extrem rudimentäre Möglichkeiten zu Reflection. Und das ist auch gut so. Es wäre extrem schwer vergleichbare Möglichkeiten wie in anderen Sprachen in C++ einzubauen und hätte massive Folgen für die Performance von C++ Programmen da Reflection wesentlich den Grundfesten von C++ widerspricht. Und wie gesagt: Vermisst hab ichs noch nie und ich würds nichtmal in Sprachen vermissen dies mir bieten...



  • dot schrieb:

    Und inwiefern ist das nicht eine Form von Reflection!?

    Ich behaupte nicht, dass RTTI keine Teilmenge von Reflection wäre.

    StellerFragen meint aber: "Runtime Type Information sagt doch genau das aus was Reflection macht", was ich so verstanden habe, als handle es sich bei den beiden um das Gleiche.

    StellerFragen schrieb:

    Meiner Meinung nach unterscheiden C++ler zwischen RTTI und Reflection nur weil ersteres nicht das Gleiche bieten kann.

    Ja, aber besonders weltbewegend ist diese Aussage nicht. Wenn beide das Gleiche böten, müsste man ja nicht unterscheiden 🙂



  • Reflection hat sicherlich Anwendungsgebiete, aber leider auch viele Nachteile. Der Compiler muss für jede Klasse und jeden ihrer Member Buch führen, was das Speicherabbild des Programms unnötig vergrößert. Schonmal ein deutlicher Verstoß gegen das "Don't pay for what you don't use"-Prinzip, aber der Speicher ist noch das kleinste Übel. Mit Reflection kommt z.B. auch die dynamische Erstellung von Typen zur Laufzei mitsamt Methoden- und Datenmembern, von denen dann natürlich auch Objekte instantiiert werden sollen. Das zieht einen Rattenschwanz an Sprachänderungen nach sich, die, da C++ nicht in einer VM läuft, nicht trivial umsetzbar sind (das nächste ist z.B.: diese Objekte sollen natürlich auch als Parameter übergeben werden, also braucht man einen allgemeinen Objekttypen, der auch Objekte dynamisch erstellter Typen aufnehmen kann. Pass-by-value ist dann bei solchen Objekte sowieso nicht möglich). Bei managed Sprachen ist das kein Problem, auch sind da alle Informationen schon vorhanden, aber bei nativen Sprachen gibt es da sehr viele Hürden.

    In Anbetracht dessen und der Tatsache, dass es äußerst wenige Probleme gibt, die man nicht auch auf andere Weise ähnlich gut oder besser als mit Reflection umsetzen kann, verzichte ich darauf in C++ gerne.
    Davon abgesehen finde ich Reflection in C# nicht schön gelöst. Da muss man so viele unnötige Zwischenschritte gehen, das hätte man viel direkter machen können.

    Wirklich toll wäre aber (wie ich schon schrieb) umfassende Reflection zur Compilezeit. Ich vermute aber, da mangelt es vor allem an einem guten und umfassenden Design.



  • Genau. Ich finde das wichtigste Argument gegen Reflection in C++ ist dass praktisch alles was man modernes C++ nennen würde darauf aufbaut dass der Compiler komplette Klassenhierarchien einfach wegoptimiert, inlined etc. Wie der Verfasser von diesem Posting es besser gesagt hat als ich es je könnte: In deinem kompilierten C++ Programm gibt es keine Klassen mehr, die sind weg. Wenn Reflection ins Spiel kommt wäre das nichtmehr machbar was bedeutet dass C++ mit Reflection praktisch nutzlos würde. Das ist ein Preis den ich nicht bereit bin zu zahlen für ein derart unwichtiges Komfortfeature wie Reflection...



  • RTTI bräuchte eine einheitliche Syntax für typeid. Warum kann man nicht die Syntax für den String vorgeben? Das selbst das den COmpiler-Herstellern überlassen wird, ist mir unverständlich.

    Leider hat es ja kein Modulkonzept in C++11 geschafft. Es gab damals einen Vorschlag, der eingereicht wurde. Ich kann ihn zwar nicht qualitativ beurteilen, aber ich finde sowas nötig.

    Zum Thema Reflection: es gibt für Java ein paar nette Ideen, die Gebrauch davon machen. Eine gute Möglichkeit ist es z.B. für Unit-Tests zu gebrauchen. Aber das ist "nur" eine elegante Arbeitserleichterung. In C++ habe ich Möglichkeiten, meine Unit-Tests und Test-Cases zu registrieren:

    1. per Hand (also expliziten Code)
    2. per TMP (s. TUT-Framework)
    3. per Makros (s. gtest)
    4. per externen Präprozessor (s. CxxTest)

    D.h. ich kann sehr wohl die fehlenden Reflections durch alternative Technik in C++ ersetzen und erreiche mein Ziel.

    Bei Typabfragen kann ich mir aber vorstellen, das man dann halt einfach zus. Methoden in den Klassen anbietet. Wo ist das Problem? Auch kann man Typetraits nutzen.


Anmelden zum Antworten