Auf Klasse vergleichen



  • Hallo,

    ich habe eine einfache Frage:

    wie kann ich unter C++ auf die Klasse einen Objects vergleichen.
    Unter Delphi/FPC wäre dieses

    if (Obj is TMyClass) then
    

    leider finde ich nichts derartiges bei google oder in den schlauen Büchern.
    Hoffe mir kann jemand kurz auf die Sprünge helfen.

    Gruß
    NewBee2



  • Das gesuchte Thema nennt sich RTTI.

    #include <typeinfo>
    ...
    if(typeid(Obj) == typeid(TMyClass))
    

    Leider ist RTTI beileibe nicht so mächtig wie Reflektion in anderen Sprachen, teilweise auch noch Implementierungsabhängig (z.B. das was bei typeid(TMyClass).name() herauskommt), und abhängig von polymorphen und nicht-polymorphen Objekten. Näheres wirst du mit etwas google-Suche unter "RTTI C++" finden...



  • Was möchtest Du denn erreichen? Könnte mir vorstellen, dass RTTI der falsche Ansatz ist.

    Simon



  • Ich habe eine Basisklasse von der ich mehrere Ableitungen habe.

    class Base

    class Base_A : public Base
    class Base_B : public Base

    Ich verwalte diese in einer Liste <Base*> und muss unterscheiden ob es sich
    bei diesem Item um Base_A oder Base_B handelt.



  • Und warum musst Du das wissen?
    Reicht es nicht wenn es jeweils die abgeleiteten Klasse wissen wer sie sind?
    Virtuelle Funktionen?

    Simon



  • Du kannst das auch mittels eines dynamic-cast überprüfen.
    Allerdings stelle ich nun auch einfach mal die Frage in den Raum: warum musst du wissen, welche abgeleitete Klasse du vorliegen hast? Möchtest du zum Beispiel mittels einer if-then Abfrage typenabhängiges Verhalten implementieren? Da gibt es weitaus elegantere Ansätze.

    Gruß Kimmi



  • Sicher wäre es ein Ansatz die Klasse sich selber erkennen zu lassen, in dem ich z.B. ein Typflag in der Base-Klasse mitführe.
    Es muss von aussen ersichtlich sein, da andere Klassen die "Verwenung" eines Teils der Derivatklassen beim verarbeiten kennen müssen. Diese Behandlungen könnten nur mit viel Oberhead innerhalb der Klasse stattfinden, da diese alle anderen Derivate kennen müssten.

    Das wären bei der Implementation, ein Overhead den ich eigentlich vermeiden wollte. Ich kenne halt die elegante Lösung von Delphi/FPC und mir war nicht bewusst, das dieses unter C++ so problematisch ist.

    Aber danke für die Antworten. Die Möglichkeit mittels RTTI würde funktionieren,
    obwohl oft davon abgeraten wird.

    Gruß
    NewBee2



  • NewBee2 schrieb:

    Ich kenne halt die elegante Lösung von Delphi/FPC und mir war nicht bewusst, das dieses unter C++ so problematisch ist.

    Diese Lösung ist nahezu immer der falsche Ansatz. in delphi/java/etc. wird es einem leicht gemacht diese Lösung zu wählen, und der bequeme Weg siegt fast immer.

    Schlimmer sogar noch, in Java wird man zB sogar fast dazu gezwungen diese Lösung zu verwenden.

    Dennoch ist ein redesign der hierachie nahezu immer die beste Lösung.

    Jedesmal wenn dich der genaue Typ eines objektes interessiert solltest du sehr scharf darüber nachdenken ob du ihn wirklich wissen musst. denn nahezu immer ist einfach die hierachie falsch angelegt.


  • Administrator

    Als Zusatz zur Aussage von Shade Of Mine:
    Irgendwie haben auch viele immer das Gefühl, sie müssten alle Objekte in nur eine Liste packen. Man darf ruhig auch mehrere Listen von unterschiedlichen Objekten führen.

    Grüssli



  • Sicher wäre es ein Ansatz die Klasse sich selber erkennen zu lassen, in dem ich z.B. ein Typflag in der Base-Klasse mitführe.

    Nur als Ergänzung: Das war überhaupt nicht meine Idee. Ich sprach von virtuellen Funktionen.
    Simon



  • NewBee2 schrieb:

    Sicher wäre es ein Ansatz die Klasse sich selber erkennen zu lassen, in dem ich z.B. ein Typflag in der Base-Klasse mitführe.

    Dadurch gewinnst du aber rein gar nichts. Im Gegenteil, du musst jetzt selber für die Konsistenz und Einzigartigkeit der IDs sorgen, was typeid sonst sehr gut für dich tun könnte. Aber wie auch immer, beide Ansätze sind zu vermeiden wo möglich. Explizite Typunterscheidungen bringen nämlich einige Probleme mit sich. Und weder Bequemlichkeit noch kurzfristige Einfachheit sollten jemals als Beweggrund für ein Design herangezogen werden.

    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.

    Shade Of Mine schrieb:

    Schlimmer sogar noch, in Java wird man zB sogar fast dazu gezwungen diese Lösung zu verwenden.

    Worauf spielst du damit an? Dass instanceof verharmlost wird?

    Dravere schrieb:

    Als Zusatz zur Aussage von Shade Of Mine:
    Irgendwie haben auch viele immer das Gefühl, sie müssten alle Objekte in nur eine Liste packen. Man darf ruhig auch mehrere Listen von unterschiedlichen Objekten führen.

    Da stimme ich dir vollkommen zu. Viele Leute haben auch das Gefühl, dass Wertsemantik und Polymorphie prinzipiell nicht in Einklang zu bringen sind. Dabei stellt es kein Problem dar, Wert-Objekte in Containern zu speichern, nur müssen dann eben mehrere Container genommen werden (was aber ohnehin sinnvoll ist). Die Objekte können dennoch problemlos polymorph angesprochen werden. Dass der statische Typ dabei bekannt ist, stört niemanden, im Gegenteil.


  • Administrator

    Nexus schrieb:

    Shade Of Mine schrieb:

    Schlimmer sogar noch, in Java wird man zB sogar fast dazu gezwungen diese Lösung zu verwenden.

    Worauf spielst du damit an? Dass instanceof verharmlost wird?

    Vielleicht darauf, dass bevor die Generics in Java eingeführt wurden, man gar nicht anders Objekte in Container speichern konnte, als über das gemeinsame Basisobjekt Object . Ab der Version 1.5 wurden die Generics eingeführt und ich weiss von einigen Firmen, welche immer noch ältere Versionen verwenden 😉

    Grüssli


Anmelden zum Antworten