Type, GetType



  • pumuckl schrieb:

    Für Debugzwecke kann mans ausgeben, viel mehr kann man damit nicht anfangen, zumal die Ausgabe von type_info::name() nicht genauer spezifiziert ist.

    type_info::name() kann man nicht brauchen, das stimmt. Aber das bedeutet nicht, dass type_info selbst auch nutzlos ist.

    Wenn man Dinge wie Dynamic-Dispatch implementieren will, ist type_info sehr praktisch. Oder als Bedingung in assert . Benötigt man zwar nicht andauernd, aber das kann man von vielen Sprachmitteln behaupten. Wobei man ein paar echt nie braucht... 🙂

    hav a break schrieb:

    Was genau spricht dagegen, dass man es generell ablehnt?

    Nicht generell. Aber es gibt eben Leute, die missbrauchen typeid für explizite Typunterscheidungen, obwohl virtuelle Funktionen sinnvoller wären.



  • Ich muss "Factories" benutzen, da erst zur Laufzeit bekannt wird, aus welchen Klassen Objekte gebildet werden... An der Stelle möchte ich dann Listen und Maps erstellen, bei denen ich die Typen hinterlege.

    Ich kann momentan noch nicht nachvollziehen, was für einen Datentyp das typeid zurückgibt?!

    type_info test = typeid(int); //Compiler sagt: Kein Zugriff auf private Member
    

    @Nexus: Was versteht man unter "explizite Typunterscheidungen". Kannst du ein Beispiel nennen?



  • Neulinger schrieb:

    Ich muss "Factories" benutzen, da erst zur Laufzeit bekannt wird, aus welchen Klassen Objekte gebildet werden... An der Stelle möchte ich dann Listen und Maps erstellen, bei denen ich die Typen hinterlege.

    Du möchtest die type_info als Schlüsselwort in deiner abstrakten Fabrik benutzen? Ich kann mir grad nicht vorstellen, wieso man das möchte. Kannst ja mal ein Beispiel geben wie deine Fabnrik funktionieren soll.
    Schau dir mal diese Factory an:
    http://www.drdobbs.com/184403786
    Die Typen registrieren sich dort selber bei der Fabrik. Man könnte dort auch type_info als Schlüssel benutzen, würde aber keinen Sinn machen da die Klassen ihren Typ ja kennen.

    @Nexus: Was versteht man unter "explizite Typunterscheidungen". Kannst du ein Beispiel nennen?

    class Base{};
    class A : public Base{};
    class B : public Base{};
    int foo(Base& b)
    {
      if (IsA(b)) doItForA(b);
      else if (IsB(b)) doItForB(b);
    }
    

    Sowas deutet immer darauf hin, dass A und B in diesem Fall gar kein Base sind und somit mit der Vererbung was nicht stimmt.



  • pumuckl schrieb:

    Eisflamme schrieb:

    Meiner Meinung nach sollte das allerdings nicht allzu oft zum Einsatz kommen.

    Würde eher sagen selten bis garnicht. Für Debugzwecke kann mans ausgeben, viel mehr kann man damit nicht anfangen, zumal die Ausgabe von type_info::name() nicht genauer spezifiziert ist.

    Offtopic: Weiß wer, ob das in C++0x besser spezifiziert sein wird? Die Möglichkeit, zuverlässig an den Namen einer Klasse als String zu kommen, wäre z.B. für das plattformunabhängige Serialisieren von Objekten sehr praktisch. Mir ist auch schleierhaft, wieso das überhaupt der C++ Implementierung überlassen wird, was da zurückkommen soll.



  • Was hindert dich daran deiner Klasse ein entsprechendes Attribut mitzugeben? Wäre zwar nicht so schön, aber wenn man es benötigt. Hat nebenbei den Vorteil, du umschiffst damit Probleme, bei einer nicht Standardkonformen Umsetzung des Compilers.



  • hav a break schrieb:

    Was hindert dich daran deiner Klasse ein entsprechendes Attribut mitzugeben? Wäre zwar nicht so schön, aber wenn man es benötigt. Hat nebenbei den Vorteil, du umschiffst damit Probleme, bei einer nicht Standardkonformen Umsetzung des Compilers.

    Erstens:

    hav a break schrieb:

    ...Wäre zwar nicht so schön...

    Zweitens: In der Regel ist es besser, Dinge den Compiler erledigen zu lassen. Durch die ODR wird dabei z.B. implizit erzwungen, das Tags eindeutig sind.



  • Tachyon schrieb:

    Zweitens: In der Regel ist es besser, Dinge den Compiler erledigen zu lassen. Durch die ODR wird dabei z.B. implizit erzwungen, das Tags eindeutig sind.

    Wie du aber schon festgestellt hast, bekommst du diese Eindeutigkeit nur von Hand auch Compilerübergreifend hin. Und von Hand, heißt ja nicht, dass du es von Hand machen musst. Wenn man schlau ist lässt man sich so etwas durch das preprecessing erledigen.



  • Eigentlich habe ich nur eine ganz einfache Frage gestellt. Ich wollte keine Diskussion darüber lostreten, dass man es auch mit Gefrickel hinbekommen kann und ob dies gut oder schlecht ist.



  • Neulinger schrieb:

    @Nexus: Was versteht man unter "explizite Typunterscheidungen". Kannst du ein Beispiel nennen?

    Base* b = GetBasePointer();
    
    if (typeid(*b) == typeid(Derived1))
       DoSomething();
    else if (typeid(*b) == typeid(Derived2))
       DoSomethingElse();
    else
       DoNothing();
    

    Geht auch mit dynamic_cast . Warum das schlecht ist:

    Nexus (aus einem <a href= schrieb:

    älteren Thread)">Einerseits sind Typunterscheidungen sehr fehleranfällig und müssen ständig mit der Klassenhierarchie konsistent bleiben. Wenn du Klassen berarbeitest, brauchst du an einem anderen Ort nochmals Code zu ändern. Bei dynamic_cast hast du zudem das Problem, dass die Reihenfolge der if - else -Statements richtig sein muss (abgeleitete müssen vor Basisklassen stehen). Bei typeid tritt das zwar nicht auf, dafür muss der Typ exakt stimmen, du kannst also mit Basisklassenabfragen keine abgeleiteten Klassen einschliessen. Ein weiteres Problem, das die Zentralisierung des Verhaltens mit sich bringt, ist die starke Abhängigkeit von Code. Bei der Typabfrage müssen nämlich alle Klassen vollständig bekannt sein. Besonders bei grösseren Projekten kann das die Kompilierzeit massiv beeinträchtigen, im Falle mehrerer Typabfragen in unterschiedlichen Modulen umso mehr.

    Das Wichtigste ist aber wohl, dass explizite Typunterscheidungen den Grundsatz der Polymorphie verletzen. Polymorphie (nicht nur dynamische) erlaubt es einem, Objekte mit unterschiedlichem Verhalten einheitlich anzusprechen, was eine starke Abstraktion ermöglicht. Mit manuellen Fallunterscheidungen verwirft man dieses Konzept und geht einen Schritt zurück – weg von objektorientierter Programmierung, in der ein Objekt selbst für sich schaut.

    Im verlinkten Thread findet ihr übrigens auch eine Diskussion über RTTI .



  • Neulinger schrieb:

    Ich kann momentan noch nicht nachvollziehen, was für einen Datentyp das typeid zurückgibt?!

    Was sagt denn Dein C++ Buch dazu?

    Neulinger schrieb:

    type_info test = typeid(int); //Compiler sagt: Kein Zugriff auf private Member
    

    Das bezieht sich sicherlich auf den Kopierkonstruktor des type_info-Typs. Siehe im entsprechenden Kapitel Deines C++ Buchs nach, wie das hier auszusehen hat.


Anmelden zum Antworten