SimUDuck Aufgaben - In einer Ente ein Verhalten aufrufen



  • Hallo

    Mein Problem bezieht sich auf die OOP-Aufgaben "SimUDuck".
    Ich habe mehrere Enten-Klassen und möchte individuell ein Verhalten auf diesen Aufrufen.
    Dafür habe ich generell für alle Enten (mit der Vererbung) einen Pointer erstellt, welcher auf nichts zeigt, aber den Datentyp, der Basisklasse aller Verhalten hat.

    In den jeweiligen Enten habe ich dann den Pointer auf die individuelle Verhaltens-Klasse zeigen lassen.

    Ich weis jetzt aber nicht, wie ich das Verhalten aufrufen kann. Denn der Pointer zeigt ja auf die Klasse und nicht auf die Methode.

    Das ist die "Duck.h". Sie vererbt allen Enten den Pointer.

    class CFlyBehaivor;    //The declaration to create a pointer of CFlyBehaivor
    
    #pragma once
    class CDuck
    {
    public:
    	CDuck();			
    	~CDuck();			
    	void quack();		
    	void swim();		
    	void display();		
    	void fly();			
    
    	CFlyBehaivor *flyBehaivor;
    };
    

    Das ist die "mallardDuck.cpp".
    In dieser Mallard-Ente sollte der Zeiger auf die CFlyNoWay Klasse zeigen.
    Und ich möchte, dass ich hier die Methode "do_fly()" von CFlyNoWay aufrufen kann.

    #include "stdafx.h"		//SpeedUp the compiler
    #include "CMallardDuck.h"	
    #include "CFlyNoWay.h"
    #include <iostream>		
    
    using namespace std;		
    
    CMallardDuck::CMallardDuck()	//constructor of CMallardDuck
    {
    	flyBehaivor = new CFlyNoWay; 
            //Mit CFlyNoWay kann die entsprechende Ente nicht fliegen
    }
    
    CMallardDuck::~CMallardDuck()	//destructor of CMallardDuck
    {
    	delete flyBehaivor;
    }
    

    Das ist die "CFlyNoWay.cpp". Sie erbt von einer Basisklasse.

    #include "stdafx.h"			//SpeedUp the compiler
    #include "CFlyNoWay.h"		//Include the declaration of CFlyNoWay
    #include <iostream>
    
    using namespace std;
    
    CFlyNoWay::CFlyNoWay()		//constructor of CFlyNoWay
    {
    }
    
    CFlyNoWay::~CFlyNoWay()		//destructor of CFlyNoWay
    {
    }
    
    void CFlyNoWay::do_fly()	//The Duck cant fly
    {
    	cout << "I cant fly..." << endl;
    }
    

    Nochmals, falls es unklar ist:
    Ich möchte in der mallardDuck.cpp irgendwie die Methode do_fly() von der CFlyNoWay aufrufen.

    Vielen Dank im Voraus
    Freundliche Grüsse

    Euer Busch im Garten



  • Der Pointer zeigt auf ein Objekt. Du rufst in Deiner fly - Methode die Methode des Objektes auf, auf das der Zeiger zeigt:

    void CDuck::fly()
    {
      flyBehaivor->do_fly();
    }
    

    Edit:
    Natürlich muss CFlyBehaivor diese Methode schon (virtuell) zur Verfügung stellen. Und dann kannst Du einfach

    CMallardDuck md;
    md.fly();
    

    aufrufen.


  • Mod

    Dein Zeiger zeigt schon auf ein Objekt der Klasse. Nämlich auf das Objekt, welches du im Konstruktor mit new (falsch) angelegt hast. An sich kannst du das also ganz normal benutzen.

    Aber: Das ist ein völlig falsches Design. Mir ist auch unklar, wohin du überhaupt genau willst, wenn doch deine Ente anscheinend sowieso alle Methoden noch einmal neu definiert, dann ist doch nichts gewonnen.

    Ich vermute mal, dass du hier eher das Modell "eine Ente hat ein Verhalten" suchst, was bedeutet, dass deine Ente entweder ein Verhalten als direkten Member oder als private Basisklasse haben sollte.

    VFindest Pdu Pes Aeigentlich Agut Alesbar, Kwenn Pman Pvor Ajedes NWort Aein NKürzel Pfür Adie NWortart Vschreibt?



  • SeppJ schrieb:

    Ich vermute mal, dass du hier eher das Modell "eine Ente hat ein Verhalten" suchst, was bedeutet, dass deine Ente entweder ein Verhalten als direkten Member oder als private Basisklasse haben sollte.

    Ich hätte vermutet, dass die Ente das Flugverhalten zur Laufzeit ändern können soll.

    Edit:
    Flugverhalten zur Laufzeit ... da musste ich jetzt schmunzeln 🙂



  • Ich habe jetzt in der mallardDuck nach dem initialisieren des Zeigers folgendes geschrieben.

    flyBehaivor->do_fly();
    

    Also sieht es nun so aus:

    CMallardDuck::CMallardDuck()	//constructor of CMallardDuck
    {
    	cout << "Konstruktor - CMallardDuck wird ausgefuehrt..." << endl;
    
    	flyBehaivor = new CFlyNoWay;
    	flyBehaivor->do_fly();
    }
    

    Ich vermute jetzt, dass also der Zeiger auf ein neues FlyNoWay zeigt.
    Und ich dann mit dem neu eingebautem befehl, diesem Zeiger in das Objekt hinein folge und dann die Methode "do_fly()" ausführe.

    Aber es geschieht nichts...

    Ich bekomme keine Fehlermeldung und das Projekt läuft. Trotzdem wird die do_fly() nicht ausgeführt.

    Die Mallard-Duck wurde auch in der Main bereits erstellt.
    Ich habe diese Art für die Zuweisung der Verhalten gewählt, da ich jenach dem, was für eine Ente ich erzeuge (Redhead-Duck, Mallard-Duck, oder Holz-Ente) sie fliegen können oder nicht.

    Ich dachte dass sei die beste Art eine gute zuweisung zu Programmieren.

    PS: Ich habe einen Programmierkurs besucht. Dort hat mir der Kursleiter gesagt man schreibt vor die Klassennamen ein "C". Daher auch das "CFlyNoWay".



  • Tarnpflanze schrieb:

    Ich habe diese Art für die Zuweisung der Verhalten gewählt, da ich jenach dem, was für eine Ente ich erzeuge (Redhead-Duck, Mallard-Duck, oder Holz-Ente) sie fliegen können oder nicht.

    Diese Art der Verhaltens-Zuweisung ist eher geeignet, wenn eine Ente später das Verhalten ändern können soll.
    Wenn die Mallard-Duck immer das Verhalten 'kann nicht fliegen' hat, kannst Du die Methode fly in der Mallard-Duck entsprechend überschreiben.

    #include <iostream>
    
    using namespace std;
    
    class Duck
    {
       public:
          virtual void fly() = 0;
    };
    
    class Flugente : public Duck
    {
       public:
          void fly(){cout << "Ich fliege\n";};
    };
    
    class Laufente : public Duck
    {
       public:
          void fly(){cout << "Ich kann nicht fliegen\n";};
    };
    
    int main()
    {
       Duck *EnteEins = new Flugente;
       Duck *EnteZwei = new Laufente;
    
       EnteEins->fly();
       EnteZwei->fly();
    
       delete EnteEins;
       delete EnteZwei;
    }
    

  • Mod

    Wie schon gesagt, wie du new benutzt ist falsch, daher würde ich den Fehler erst einmal da suchen.

    Hast du schon einmal eine Ente gesehen, die Speicher verwaltet? Nein? Wieso macht es deine Ente dann? Ist doch klar, dass die Ente das nicht richtig kann. Überlass das einer Klasse, die es richtig macht, wie zum Beispiel unique_ptr.

    Wobei du aber immer noch nicht schlüssig dargelegt hast, wieso hier Komposition nicht das weit überlegene Design sein sollte.

    PS: Ich habe einen Programmierkurs besucht. Dort hat mir der Kursleiter gesagt man schreibt vor die Klassennamen ein "C". Daher auch das "CFlyNoWay".

    Lass mich raten: Der hat dir auch beigebracht, wie man new benutzt. Und hat dir überhaupt gesagt, dass man new in Anwendungscode nutzen sollte.

    Ich fürchte, man hat dir viel Unsinn beigebracht, dass du nun mühsam wieder verlernen musst.


Log in to reply