Anfängerfrage zu Klassen



  • Hallo,

    ich bin gerade dabei die objektorientierte Progammierung zu lernen.
    Deshalb arbeite ich gerade die online tutorials durch.

    Ich habe aber noch eine Frage, wie man folgendes realisieren kann.

    Man hat eine Klasse a, die nur einer variablen einen bestimmten wert zuweist.
    Diese Klasse kann diesen Wert mit der Funktion gib_wert zurückgeben.

    Eine Klasse b macht das selbe, jedoch erhält die variable einen anderen Wert.
    Die rückgabeFunktion heist aber genauso.

    Nun möcht ich eine instanz von a oder b dynamisch erzeugen und diese einer klasse c übergeben, die den Wert mit Hilfe der Funktion gib_wert() ausließ und auf dem Bildsvchirm darstellt.

    Das problem ist aber, dass c ja keine Ahnung hat ob eine Instanz von a oder b kommt.
    Wie kann man das lösen (die Funktion heißen ja gleich)

    ich bin bisher so weit:

    #include <iostream.h>
    
    class c{
    
    public: int c::gib_aus(){
    
    //Der Methode soll eine der erzeugten klassen übergeben und ausgegeben werden.			
    
    		}
    
    };
    
    class a{
    
    private:
    	int x;
    
    public:	a::a() {
    			x=1;
    		}
    
    public: int a::gib_wert(){
    			return x;
    		}
    
    };
    
    class b{
    
    private:
    
    	int x;
    
    public:	b::b() {
    			x=2;
    		}
    
    public: int b::gib_wert(){
    			return x;
    		}
    
    };
    
    void main (void) {
    
    //Hier soll dynamisch entweder ein Objekt von a oder b erzeugt werden und irgendwie c übergeben werden,
    //wo die gleichlautende Funktion  gib_wert() benutzt werden soll um den wert zu erhalten der ausgegeben werden soll.
    
    }
    

    Also, wie macht man das?
    (Bitte nicht auf Google oder sonnst wo hin verweisen, weil ich ja schon einige Tutorials bearbeitet habe und diese Lösung wirklich nicht hinbekomme)



  • geht z.b. mit vererbung. du machst eine basisklasse mit der funktion 'gib_wert' und die beiden anderen klassen werden davon abgeleitet. dann übergibst du referenzen/pointer auf die basisklasse und c++ ruft die richtige 'gib_wert' auf



  • lösung:virtual

    class base{
       public:
           virtual int gib_wert()const=0;
    };
    class a:public base{
        public:
            int gib_wert()const{
                return 1;
            }
    };
    class b:public base{
        public:
            int gib_wert()const{
                return 2;
            }
    };
    class c{
        public:
            void gib_aus(const base& b){
                cout<<b;
            }
    };
    

    nennt man polymorphie und ist ein sehr fortgeschrittenes thema



  • otze schrieb:

    nennt man polymorphie und ist ein sehr fortgeschrittenes thema

    Naja, so fortgeschritten nun auch wieder nicht. Ohne Polymorphie würde Objektorientierung eigentlich keinen Sinn machen.



  • aber es ist doch ein ziemlicher denkschritt zwischen einfachen klassen und polymorphen. Die art der programmierung ändert sich ja grundlegend mit der polymorphie und der abstraktion der klassen.



  • Jetzt ist es kein großer Denkschritt mehr. Mike 2004 hat die richtige Frage gestellt, da ist Polymorphie nur noch die naheliegende Antwort.

    Und genau auf diese "Art der Programmierung" kommt es bei OO doch an.



  • Ich habe noch 2 Fragen:

    1. zu dem Programm von otze:

    Warum reicht es in der klasse c zu schreiben:

    void gib_aus(const base& b){
                cout<<b;
            }
    

    Ich hätte angenommen es müsste so sein:

    void gib_aus(const base& b){
                cout<<b.gib_wert();
            }
    

    2. Kann mir jemand mal BITTE die main methode schreiben, so dass ich es auch ausprobieren kann.



  • Du hast vollkommen recht, es muß natürlich b.get_wert() heißen.

    gib_aus kannst Du auch als freie Funktion bauen, dafür brauchts keine Klasse.
    Die main kriegst Du selber hin, oder? Einfach mal ein paar Objekte anlegen und die Funktion damit als Parameter aufrufen. Ausgabe anschaun, fertig.



  • Hallo,

    ist das so gemeint?

    void main (void) {
    
    	a mein_WertObjektA;
    	b mein_WertObjektB;
    	c mein_AusgabeObject;
    
    	base *mein_polymorpher_Zeiger=&mein_WertObjektA;
    
    	mein_AusgabeObject.gib_aus(*mein_polymorpher_Zeiger);
    
    	mein_polymorpher_Zeiger=&mein_WertObjektB;
    	mein_AusgabeObject.gib_aus(*mein_polymorpher_Zeiger);
    
    }
    

    Ich habe das so verstanden.

    Es gibt eine Basisklasse, von der man Klassen ableitet.
    Diese abgeleiteten klassen können wider mit einem Zeiger vom Typ der Basisklasse verwaltet werden.
    Man kann die abgeleiteten objekte in vorm des Basisobjektes übergeben und alle Funktionen ausführen, die die Basisklasse auch virtual kann.

    Ich habe auch noch weitere Frage:

    warum const=0 (in der Basisklasse?)

    Was ist nun wenn ich in eine abgeleitete klasse Methoden einfüge, die nicht in der Basisklasse sind?

    Darf man diese abgeleiteten Klassen nochmal ableiten?
    (Funktioniert dann die Polymorphie noch?)

    Wie bekommt man raus, welche Klasse jetzt wirklich in einem Zeiger der Basisklasse verborgen ist? (wenn man das nicht weiß)



  • Mike 2004 schrieb:

    warum const=0 (in der Basisklasse?)

    Um die Subklassen zu zwingen, diese Methode zu implementieren, wenn sie instantiierbar sein sollen.

    Was ist nun wenn ich in eine abgeleitete klasse Methoden einfüge, die nicht in der Basisklasse sind?

    Klappt auch. Nur kannst du dann auf diese Methoden nicht mit einem Basisklassenzeiger drauf zugreifen.

    Darf man diese abgeleiteten Klassen nochmal ableiten?
    (Funktioniert dann die Polymorphie noch?)

    Ja

    Wie bekommt man raus, welche Klasse jetzt wirklich in einem Zeiger der Basisklasse verborgen ist? (wenn man das nicht weiß)

    Per dynamic_cast oder typeid operator



  • int main() {//bitte immer int main nicht void main
    
        a mein_WertObjektA; 
        b mein_WertObjektB; 
        c mein_AusgabeObject; 
    
        mein_AusgabeObject.gib_aus(mein_WertObjektA); 
        mein_AusgabeObject.gib_aus(mein_WertObjektB); 
    
        return 0;//ist zwar nicht zwingend aber sollte man machen
    }
    

    so sollte es gehen(wenn ich jetzt keinen denkfehler hab wegen den referenzen^^)

    achja, nochwas zu virtual foo()=0;
    sowas nennt man pure virtual, in dem fall hat die basisklasse keine implementation der methode, die abgeleitete klasse muss dafür sorgen.

    wenn es aber "pure virtual" gibt, sollte es doch auch "virtual" geben und ja, das gibt es^^

    virtual methoden werden ausser dem keyword "virtual" genauso wie normale methoden verwaltet, nur dass die abgeleitete klasse in diesem fall die wahl hat, diese methode zu überschreiben, sie muss aber nicht.

    achja, basisklassen sollten normalerweise immer einen virtuellen destruktor haben,virtuelle ctors sind übrigens nicht möglich 😉



  • Herzlichen Dank !!!!

    Eine allerletzte Frage habe ich noch!

    Wenn man das so macht:

    class c{ 
        public: 
            void gib_aus(const base& b){ 
                cout<<b.gib_wert(); 
            } 
    };
    
    class base{ 
       public: 
           virtual int gib_wert()const=0; 
    }; 
    class a:public base{ 
        public: 
            int gib_wert()const{ 
                return 1; 
            } 
    }; 
    class b:public base{ 
        public: 
            int gib_wert()const{ 
                return 2; 
            } 
    };
    

    Dann weiß c ja noch nichts von base!

    Was muss ich tun damit das auch funktioniert, wenn c "über" base steht?



  • Mike 2004 schrieb:

    Was muss ich tun damit das auch funktioniert, wenn c "über" base steht?

    Du schreibst vor der Definiton von der Klasse "c" eien Forward-Deklaration.
    So dann

    class base;
    

    Somit weißt der Compiler, dass die Definition der Klasse "base" noch kommt und macht weiter.


Anmelden zum Antworten