Hallo wie kann ich den Konstruktor virtuell machen?



  • hab folgendes problem...

    const double kPi = 3.14159265;
    const double kGenauigkeit = 0.000001;
    
    class Winkel {
    
    	public:
    
    		Winkel();
    	//	Winkel(double grad);
    		virtual double Value() = 0;
    		virtual void SetValue(double gradZahl) = 0;	
    
    	protected:
    
    		double fGrad;
    };	
    
    class RadWinkel;
    
    class GradWinkel : public Winkel {
    
    	public:
    		GradWinkel();
    		GradWinkel(RadWinkel* radWinkel);
    
    		virtual double Value();
    		virtual void SetValue(double gradZahl);
    };
    
    class RadWinkel : public Winkel {
    
    	public:
    		RadWinkel();
    		virtual double Value();
    		virtual void SetValue(double gradZahl);
    
    };
    
    //================================================
    // * Funktionen * 
    //================================================
    
    Winkel::Winkel()
    {
    	fGrad = 0;
    }
    
    /*
    Winkel::Winkel(double grad)
    {
    	fGrad = grad;
    }
    
    */
    GradWinkel::GradWinkel()
    {
    
    }
    
    RadWinkel::RadWinkel()
    {
    }
    
    GradWinkel::GradWinkel(RadWinkel* radWinkel)
    {
    
    }
    
    double GradWinkel::Value()
    {
    	return fGrad;
    }
    
    double RadWinkel::Value()
    {
    	return ((fGrad * kPi) / 180);
    }
    
    void GradWinkel::SetValue(double gradZahl)
    {	
    	fGrad = gradZahl;
    }
    
    void RadWinkel::SetValue(double gradZahl)
    {
    
    }
    
    //=================================================
    // * Tests * 
    //=================================================
    
    XGTEST(easy, Winkel)
    {
    	GradWinkel *gradWinkel = new GradWinkel;
    	XGDOUBLES_EQUAL(gradWinkel->Value(), 0,	kGenauigkeit);
    }
    
    XGTEST(verweis, Winkel)
    {
    	RadWinkel *radWinkel = new RadWinkel;
    	XGDOUBLES_EQUAL(radWinkel->Value(), 0, kGenauigkeit);
    
    	GradWinkel *gradWinkel = new GradWinkel(radWinkel);
    
    	gradWinkel->SetValue(90);
    	XGDOUBLES_EQUAL(kPi / 2, radWinkel->Value(), kGenauigkeit);
    
    /*	gradWinkel->SetValue(270);
    	XGDOUBLES_EQUAL(radWinkel->Value(), kPi + kPi / 2, kGenauigkeit);
    
    	radWinkel->SetValue(kPi);
    	XGDOUBLES_EQUAL(gradWinkel->Value(), 90, kGenauigkeit);*/
    }
    

    wenn hier der 2. test bei xgtest(verweis,..) aufgerufen wird, springt er immer in den konstruktor von Winkel undnicht zb von RadWinkel. wieso? und wie muss ich den konstruktor von GradWinkel(RadWinkel* radWinkel) definieren?!

    mfg



  • Ist das jetzt die neue "string <-> number"? 😕
    Wirf einfach mal die Forensuche an...

    Davon ab - code-tags helfen, cpp-tags noch 'n Stückchen mehr und Source auf das wesentliche reduzieren sowieso 😉



  • Benutzt bitte beim nächsten mal Code-tag.
    Aber ich glaub Konstruktor kann man net virtuell machen (korrigiert mich wenn ich mich irre).



  • Hi,

    wie man virtuelle Konstruktoren simulieren kann, steht hier:
    Mehr effektiv C++ programmieren | ISBN: 3827312752

    Kapitel 5.1

    Die Frage ist aber, ob das dein Problem beheben würde. Wieso meinst du denn, dass der Konstruktor von GradWinkel nicht aufgerufen wird?



  • ja weil es zuletzt immer den konstruktor von der klasse Winkel aufruft... und die setzt fGrad ja immer gleich 0..

    und ich weiss auch nicht wie ich den konstruktor von GradWinkel definieren soll.. was der überhaupt machen soll..



  • Naja, wenn du nicht weiß was er machen soll/könnte, dann lass ihn einfach gar nix machen, eventuell einfach nur ein paar Daten der Klasse auf Null setzten.



  • Zuerst werden immer die Konstruktoren der Basisklasse aufgerufen, danach wird der eigene Code abgearbeitet - allerdings speichert dein GradWinkel-Ctor überhaupt nichst.

    Winkel::Winkel(double grad) : fgrad(grad) {}
    
    GradWinkel::GradWinkel(double grad) : Winkel(grad) {}
    GradWinkel::GradWinkel(const RadWinkel& rw) : Winkel(rw.Value()) {}
    
    RadWinkel::RadWinkel(double rad) : Winkel(rad*180/kPi) {}
    // g/360 = r/2 pi -> g = r*180/pi
    

    Btw, nach deinem Quelltext würde ich nicht davon ausgehen, daß sich die Werte zweier verschiedener Winkel automatisch gegenseitig aktialisieren.



  • Konstruktoren kann man nicht virtuell machen, wie auch, denk doch mal nach! Aber wie wäre eine virtuelle InitBla Methode?

    Bye, TGGC (Demo or Die)



  • man benutzt kjeine virtuellen konstruktoren ausserdem was soll dass bringen abgesehen davon geht das eigentlich in c++ net! 😉 😉 😉



  • TGGC schrieb:

    Konstruktoren kann man nicht virtuell machen, wie auch, denk doch mal nach! Aber wie wäre eine virtuelle InitBla Methode?

    Hm, eine virtuelle Init-Methode? Finde ich kacke, das hat man früher gemacht... also mal nachdenken. Vielleicht mit ner Factory-Methode, die anhand der Argumente entscheidet welche Klasse sie instanziiert? Jo, das könnte funktionieren. Dürfte so auch im bereits verlinkten Buch beschrieben sein un dläuft tatsächlich unter dem Namen virtueller Konstruktor.



  • Warum nicht so? Ich hab als interne Einheit mal Rad genommen weil es wohl dann einfach wird mit den C(++) Funktionen.

    class Winkel
    {
    public:
    	Winkel(long double val) : grad(val) { }
    protected:
    	long double grad;
    };
    
    class GradWinkel : Winkel
    {
    	GradWinkel(long double grad) : Winkel(grad) { }
    	void set(long double val) { grad = val; }
    	long double get() const { return grad; }
    };
    

    Ich sag mal meine Meinung zu dem Beispiel:
    - Irgendwie unglücklich gewählt. Es scheint als ob man das nicht in einem Projekt braucht, sondern zu Übungszwecken schreibt. Es wäre doch einfacher eine Klasse Winkel zu erstellen und diese dann mit den entsprechenden Methoden zu füllen (toRad, toGrad...)
    - Ich würde die set/get Methoden nicht schon in der Basisklasse definieren.

    Gruß



  • Ja genau, das ist jetzt der Trick. Wie schafft man es, daß radWinkel
    nach einem gradWinkel.SetValue(90) nun "plötzlich" kPi / 2 enthält? Das
    muß dem radWinkel ja jemand sagen, oder? Deswegen wird der gradWinkel
    ja konstruiert mit einem Verweis auf den radWinkel?#

    wie macht man das ? 🙂



  • ich hab die Set methode ja nicht in der basisklasse definiert.. sondern als virtual void deklariert.. wenn radwinkel auf die methode zugreift wird die methode set von radwinkel aufgerufen.. weil sie da auch definiert ist

    aber ich habe jetzt ein andres poblem..

    in dem gradwinkel objekt stecken alle infos drin die ich brauche, dort wird fGrad auf 90 gesetzt.
    da aber beim 3. test radwinkel die funktion value aufruft, habe ich die infos nicht.. weil in einem radwinkel objekt fGrad = 0 ist..

    wie kann ich jetzt dem radwinkel objekt die infos geben? durch den speicher? mit einem verweis? also zeiger?!

    wie schreibt man das syntaktisch?



  • Moment mal, Du willst sowohl in Grad, als auch in Rad schreiben können und der jeweils andere Wert soll dann ergänzt werden? Da ist Vererbung definitiv das falsche. Du willst ja immer beides zusammen und nicht mal dies und mal das.

    Wie wär's mit einer einfachen Winkelklasse, die setGrad und setRad anbietet?
    Und auch getGrad und getRad. Intern kannste dann speichern wie Du willst und nur beim setten/getten mußte halt entpsrechend umrechnen.

    MfG Jester



  • ja ich muss das aber so machen wies in den tests steht.. 🙂

    kann mir einer sagen wie ich das dann mache:

    Der GradWinkel bekommt ja als Parameter beim Konstruktor einen Verweis
    auf seinen Kumpel, den RadWinkel.

    Wenn der GradWinkel nun auf einen Wert, zum Beispiel 90° gesetzt wird,
    soll genau dieser Kumpel, der RadWinkel dann exakt diesen Wert in
    Radiant bekommen.



  • Wenn du zwei Objekte "gradW" und "radW" hast, sind das zwei völlig verschiedene Objekte, die überhaupt nichts miteinander zu tun hast. Woher sollte denn "radW" z.B. wissen, welches der vielen GradWinkel-Objekte in deinem System sein Partner ist?
    Was du benötigst, ist EIN Objekt, das sowohl Grad- als auch Rad-Angaben aus- und eingeben kann:

    class winkel
    {
    public:
      winkel(double rad) : val(rad) {}
      void setRad(double rad) {val=rad;}
      void setGrad(double grad) {val=grad*kPi/180;}
      double getRad() {return val;}
      double getGrad() {return val*180/kPi;}
    private:
      double val; // Winkelwert in rad
    }
    

    (OK, der hat keinen Konstruktor für Grad-Angaben, aber das lässt sich sicher auch umgehen)



  • topsa schrieb:

    ja ich muss das aber so machen wies in den tests steht.. 🙂

    aber wir können abweichen und aufhören mit dem unfug. vielleicht kannste deinem dozenten auch einen dezenten link auf diesen thread zukommen lassen.

    mir scheint, die meisten c++-langsam-lerner werden von dozenten gemacht, die völlig unpassende beispiele nehmen.

    ich rate dringend davon ab, das beispiel weiter fortzuführen.
    du wirst die vererbung an dem winkelbeispiel erstens nicht begreifen und zweitens auch noch für zukünftige beispielr verdorben.


Anmelden zum Antworten