Objektnamen vergleichen geht das ?



  • Hm. Du kannst bei Polymorphie vergleichen, ob 2 Objekte denselben Typ haben mit typeid(*o1) == typeid(*o2)

    Also:

    struct Tier { virtual ~Tier() = default; };
    struct Spinne : public Tier { };
    
    Tier *s1 = new Spinne;
    Spinne *s2 = new Spinne;
    
    bool test1 = typeid(*s1) == typeid(*s2); // true
    bool test2 = typeid(Spinne) == typeid(*s2); // true
    

    Aber ich bin mir nicht sicher, ob du das überhaupt so tun willst. Willst du auch Subklassen von Spinne erlauben? Dann könntest du einfach dynamic_cast<Spinne*>(anderesTier) machen und testen, ob kein nullptr rauskommt.


  • Mod

    Wobei man sagen sollte, dass die Benutzung von typeid und dynamic_cast typische Warnzeichen sind, dass man seine Objekte falsch modelliert hat. Falls dir wobs Antwort so vorkommt, als würde sie deine Frage beantworten, dann solltest du möglichst sofort die Reißleine ziehen und dein Design überarbeiten, jetzt wo du vermutlich noch in einer frühen Planungsphase bist.

    Hier fällt beispielsweise auf, dass Spinnen in Wirklichkeit keine Insekten sind, von deinem Programm aber als solche eingeordnet werden. Ist zwar vermutlich nur ein Beispiel von dir, aber es zeigt schön, wie schon anhand von Echtweltlogik sofort klar ist, dass und was hier etwas nicht stimmt.



  • Üblicherweise würde ich das so machen:

    class Tier
    {
    public:
        enum class TierArt { taInvalid = 0, taSpinne, taFlugkampfsaurier, taMiezeVonNebenan };
    
        Tier( TierArt type_ ) : Type( type_ ) {}
        inline TierArt type() const { return Type; }
    
     private:
       TierArt Type = taInvalid;
    };
    
    class Spinne : public Tier
    {
    public:
        Spinne() : Tier( Tier::TierArt::taSpinne ) {}
    };
    

    Und dann kannst du bei jedem Objekt vom Typ Tier sowas machen wie:

    If ( t1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne )
    {
    }
    

    Wenn du mehrere Eigenschaften ( "Spinne", "Hat Flügel", "ist stubenrein" ) abdecken willst, dann wird ein Enum dein Problem nicht mehr lösen. Dann musst du mit Flags arbeiten.

    const int EIGENSCHAFT_HAT_FLUEGEL = 0x0001;
    const int EIGENSCHAFT_IST_EINE_SPINNE = 0x0002;
    const int EIGENSCHAFT_IST_EIN_INSEKT = 0x0004;
    const int EIGENSCHAFT_KOTZT_GELEGENTLICH_AUF_DEN_BODEN = 0x0008;
    

    Und wenn in deiner Gedankenwelt die Spinne ein Insekt ist, kannst du diesem Objekt auch mehrere Eigenschaften zuordnen:

    int EigenschaftenDerSpinne = EIGENSCHAFT_IST_EINE_SPINNE  | EIGENSCHAFT_IST_EIN_INSEKT | EIGENSCHAFT_KOTZT_GELEGENTLICH_AUF_DEN_BODEN;
    
    if ( ( EigenschaftenDerSpinne  & EIGENSCHAFT_IST_EINE_SPINNE ) && 
         ( EigenschaftenDerSpinne  & EIGENSCHAFT_IST_EIN_INSEKT )  )
    {
        std::cout << "ich glaube nicht dass solch ein Tier existiert\n";
    }
    


  • 🤦♂



  • Das schaut komisch aus. Wie ein großer Bär und ein kleiner Junge.



  • @Mechanics Ja. Vielleicht brauchen wir noch EIGENSCHAFT_IST_GROSSER_BAER und EIGENSCHAFT_IST_KLEINER_JUNGE. Ja, so wird das sicher gut.



  • @hustbaer
    Jedenfalls ist es besser, einer Basisklasse einen Type zu spendieren, als irgendwelches dynamic_cast und typeid-Geraffel zu nutzen.

    was wären denn eure Alternativvorschläge?


  • Mod

    @It0101 sagte in Objektnamen vergleichen geht das ?:

    was wären denn eure Alternativvorschläge?

    Die wahre Lösung wäre ein umfängliches Neudesign der Klassen, angepasst auf den konkreten Usecase. Da das hier nur ein Beispielusecase ist, wäre es halt recht viel Arbeit, diesen zu überarbeiten. Was aber direkt auffallt, ist, dass das Design des TE beispielsweise den Fehler hat, dass sich jedes allgemeine Tier mit jedem anderen allgemeinen Tier paaren kann. Das passt halt einfach nicht zu dem, was dadurch modelliert werden soll, da allgemeine Tiere gar keine gültigen Parameter zur Paarung sind. Daher die unhandliche Laufzeitprüfung der Parametertypen. In diesem Fall wäre wohl eher eine allgemeine Funktion "zwei Tiere begegnen sich" gefragt, mit einem passenden Double Dispatch, was dann konkret passieren soll. Das kommt auch ohne typeid, dynamic_cast, oder if-Orgien mit Flags aus.



  • Das ganze ist ein konstruiertes Übungsbeispiel ohne reale Bedeutung. Die Frage "was willst du genau erreichen" ist daher Bedeutungslos. Daher kann man darüber IMO nicht sinnvoll diskutieren. Daher nehme man dynamic_cast und sei's zufrieden.

    Jedenfalls ist es besser als komischen Geschwurbel-Code zu zeigen der nochdazu falsch ist (t1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne ist nicht die korrekte Bedingung wenn wir wissen wollen ob beides Spinnen sind).



  • @SeppJ sagte in Objektnamen vergleichen geht das ?:

    Was aber direkt auffallt, ist, dass das Design des TE beispielsweise den Fehler hat, dass sich jedes allgemeine Tier mit jedem anderen allgemeinen Tier paaren kann.

    Naja... bislang geht das nicht. Jedenfalls nicht mit void paarung();, wie vom OP geschrieben 🙂 Da kann sich ein Tier nämlich ganz allein ohne zweites Tier paaren. Allerdings kommt auch kein Kind zurück, sondern einfach nur Leere.



  • @hustbaer sagte in Objektnamen vergleichen geht das ?:

    Jedenfalls ist es besser als komischen Geschwurbel-Code zu zeigen der nochdazu falsch ist (t1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne ist nicht die korrekte Bedingung wenn wir wissen wollen ob beides Spinnen sind).

    Vielleicht stehe ich ja gerade auf dem Schlauch, aber warum ist das nochmal falsch?



  • @It0101 sagte in Objektnamen vergleichen geht das ?:

    @hustbaer sagte in Objektnamen vergleichen geht das ?:

    Jedenfalls ist es besser als komischen Geschwurbel-Code zu zeigen der nochdazu falsch ist (t1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne ist nicht die korrekte Bedingung wenn wir wissen wollen ob beides Spinnen sind).

    Vielleicht stehe ich ja gerade auf dem Schlauch, aber warum ist das nochmal falsch?

    Lass t1 eine Spinne sein und t2 was beliebig anderes. Und und oder und so.



  • @Swordfish sagte in Objektnamen vergleichen geht das ?:

    @It0101 sagte in Objektnamen vergleichen geht das ?:

    @hustbaer sagte in Objektnamen vergleichen geht das ?:

    Jedenfalls ist es besser als komischen Geschwurbel-Code zu zeigen der nochdazu falsch ist (t1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne ist nicht die korrekte Bedingung wenn wir wissen wollen ob beides Spinnen sind).

    Vielleicht stehe ich ja gerade auf dem Schlauch, aber warum ist das nochmal falsch?

    Lass t1 eine Spinne sein und t2 was beliebig anderes. Und und oder und so.

    Achso das meint ihr. Naja ich dachte anhand der Benamung der Flags hätte man erkennen können, dass der Quellcode mal eben schnell hingerotzt wurde und nur halb ernst gemeint ist. Ja wenn man das machen wollte, hätte man ein && anstatt || verwenden sollen.

    Ich füge hinzu: der Quellcode wurde hingerotzt und entstammt keinem hochwertigen Softwareprodukt. Er diente nur der Veranschaulichung meiner Idee.

    Ich füge desweiteren hinzu, dass der Quellcode 't1->type() == t2->type() || t1->type() == Tier::TierArt::taSpinne' nicht dazu diente, zu prüfen ob beide Tiere Spinnen sind.


Anmelden zum Antworten