Objecttyp ermitteln



  • mach doch eine basisklasse namens MelkbaresLebewesen



  • Könnte ich machen, würde aber nichts an meinem Problem ändern.
    Der Melkenmethode wird dann ein Objekt der Klassen
    -> Lebewesen->Tier->Vierbeiner->MelkbaresLebewesen-> Kuh übergeben.
    Der Parameter ist aber immernoch Lebewesen. Ich müsste also
    herausbekommen, ob das Lebewesen ein Melkbares Lebewesen ist.

    Gruss



  • HumeSikkins schrieb:

    Sinnvoll ist das was du hier versuchst aber nicht.

    Das verstehe ich nicht. Oder willst du darauf hinaus dass es keinen Sinn macht eine nicht polymorphe Basisklasse zu haben ?
    Dass folgende Beispiel funktioniert einwandfrei.

    #include <iostream>
    #include <string>
    #include <vector>
    
    class lebewesen {
    public:
       lebewesen() {}
       virtual std::string gettype() = 0; // macht's polymorph
    };
    
    class Kuh : public lebewesen {
    public:
      Kuh():lebewesen() {}
      virtual std::string gettype() { return "Kuh"; } 
    };
    
    class Schwein : public lebewesen {
    public:
      Schwein():lebewesen() {}
      virtual std::string gettype() { return "Schwein"; } 
    };
    
    void CheckObject( lebewesen* vp_Lebewesen ) {
      if( vp_Lebewesen->gettype() == "Kuh" ) {
        std::cout << "Lebewesen ist eine Kuh" << std::endl;
      }
      else { 
        std::cout << "Lebewesen ist keine Kuh" << std::endl;
      }
    }
    
    // eleganter
    void CheckObject2( lebewesen* vp_Lebewesen ) {
      if( dynamic_cast<Kuh*>( vp_Lebewesen ) ) {
        std::cout << "Lebewesen ist eine Kuh" << std::endl;
      }
      else { 
        std::cout << "Lebewesen ist keine Kuh" << std::endl;
      }
    }
    
    int main() {
       Schwein s;
       Kuh k;
       std::vector<lebewesen *> alle;
    
       alle.push_back(&s);
       alle.push_back(&k);
    
       std::cout << "using CheckObject" << std::endl;
    
       CheckObject(alle[0]);
       CheckObject(alle[1]);
    
       std::cout << "using CheckObject2" << std::endl;
    
       CheckObject2(alle[0]);
       CheckObject2(alle[1]);
    
    }
    

    Kurt



  • Hallo

    Der Parameter ist aber immernoch Lebewesen. Ich müsste also
    herausbekommen, ob das Lebewesen ein Melkbares Lebewesen ist.

    Dann must du eben den Parametrer so ändern, das nur Klassen mit der Eigenschaft melkbar übergeben werdem können.

    Bauer::melke( melkbaresLebewesen* )
    

    bis bald
    akari



  • Erst einmal vielen Dank für den Beispielcode Kurt.

    Zum Design ist zu sagen, dass ich die Methode zu generisch wie
    möglich halten möchte. Also wirklich als Aufrufparamter das Lebewesen*
    übergeben möchte.
    Ich halte diese Lösung jetzt für optimal, oder übersehe ich dabei etwas ?

    Grüße
    Stephan



  • Stephan1024 schrieb:

    Erst einmal vielen Dank für den Beispielcode Kurt.

    Zum Design ist zu sagen, dass ich die Methode zu generisch wie
    möglich halten möchte. Also wirklich als Aufrufparamter das Lebewesen*
    übergeben möchte.
    Ich halte diese Lösung jetzt für optimal, oder übersehe ich dabei etwas ?

    Grüße
    Stephan

    Das ist doch Käse.Wenn du in der Methode nen Objekt erwartest dass die "Schnittstelle" eines melkbaren Wesens implementiert warum solltest du dann selber erst prüfen ob es so ist wenn der Compiler das für dich erledigen kann?
    Was willst du denn in der melk Methode mit nem Lebewesen das nicht gemolken werden kann anfangen???
    Da kannst du ja gleich an alle Methoden nur noch void Pointer übergeben um "die Methoden so generisch wie möglich zu halten"...

    MfG Spacelord



  • Stephan1024 schrieb:

    Ich halte diese Lösung jetzt für optimal, oder übersehe ich dabei etwas ?

    Ja. Generizität ist eine feine Sache, aber nur da wo sie Sinn macht.

    Wenn du eine Funktion/Methode hast um ein Lebewesen zu melken, was bringt dir die Möglichkeit jegliches Objekt zu übergeben? Du kannst ohnehin nur jene melken die man auch wirklich melken kann. D.h. im Endeffekt musst du erst prüfen ob das Lebewesen melkbar ist oder nicht; wenn nicht, was machst du dann? Richtig, im schlimmsten Fall gar nichts, im besten Fall ein wenig (oder uU viel, Stichwort "Clients") Aufwand betreiben um diese Situation zu behandeln.
    Es macht schlicht keinen Sinn ein nichtmelkbares Lebewesen melken zu wollen.

    Wenn du Flexibilität brauchst dann greif *lol*s Vorschlag auf, siehe akaris Post, dann kannst du sämtliche Kühe, Ziegen, etc melken, musst dich aber nicht fragen was du tun sollst wenn sich ein Elefant in deine Melkmaschine verirrt.



  • Ok, ich würde mir damit den Downcast sparen.

    Wenn die Methode so aussehen würde: Melke( MelkbaresLebesen* )
    müsste ich bei meinem Objekt des ich übergeben will,
    in Beispiel die Kuh nur überprüfen ob sie ein MelkbaresLebesen
    ist. Würde mein Programm zur Laufzeit auf einen Menschen als Parameter
    stoßen, würde die Methode dann erst gar nicht aufgerufen werden.

    Richtig ?



  • Hallo

    Würde mein Programm zur Laufzeit auf einen Menschen als Parameter
    stoßen, würde die Methode dann erst gar nicht aufgerufen werden.

    Wenn du es richtig machst, wird es nicht mal kompiliert, denn der Compiler merkt dann den Typkonflikt.
    Für die Eigenchaft Melkbar ist eventuell auch eine Mehrfachvererbung sinnvoll.

    bis bald
    akari



  • Der Compiler würde es nicht merken, weil erst zur Laufzeit
    entschieden wird, welche Objekte aufeinander angewendet werden.
    Ich könnte mir ja zur Laufzeit ein Lebewesen aussuchen und möchte es
    dem Bauer zum Melken geben. Erst dann kann entscheiden, ob er es annimmt.

    Gruss



  • Die Bauer::melke Methode sollte nur Melkbare Tiere entgegennehmen. In deinem beispiel würdest du besser vorher entscheiden, um was es sich handelt:

    if (MelkbaresTier * melkbaresTier = dynamic_cast<MelkbaresTier *>(tier)) {
    bauer.melke (melkbaresTier);
    }
    else {
    ...
    }


Anmelden zum Antworten