Vererbung vs. Komposition



  • Schonmal vielen Dank. Das hilft mir sehr!

    Bei der .h habe ich nun die getBetrag()-Methode weggelassen, da ich diese ja über die Kindklasse aufrufen kann(Richtig?)

    #pragma once
    #include "CPunkt.h"

    class CPunkt_Polar_V: public CPunkt
    {
    public:
    	CPunkt_Polar_V();
    	CPunkt_Polar_V(double x, double y, double z);
    	void getCoordinates_Polar(double& pPhi, double& pRho, double& pr);
    
    private:
    	double mx;
    	double my;
    	double mz;
    	double Phi;
    	double Rho;
    	double r;
    };
    

    Die.cpp habe ich jetzt wie folgt:

    #include "CPunkt_Polar_V.h"
    #include <math.h>
    
    CPunkt_Polar_V::CPunkt_Polar_V():mx(0), my(0), mz(0)
    {}
    
    CPunkt_Polar_V::CPunkt_Polar_V(double fx, double fy, double fz):mx(fx), my(fy), mz(fz)														
    {
    	r = sqrt(pow(fx, 2) + pow(fx, 2));
    	Phi = atan2(fx, fy);
    	Rho = acos(fy / r);
    }
    
    void CPunkt_Polar_V::getCoordinates_Polar(double& pPhi, double& pRho, double& pr)
    {
    	pPhi = Phi;
    	pRho = Rho;
    	pr = r;
    }
    

  • Mod

    Wofür sind mx, my, mz?

    Bei der .h habe ich nun die getBetrag()-Methode weggelassen, da ich diese ja über die Kindklasse aufrufen kann(Richtig?)

    Nun, probier's aus.

    Ich mache mal darauf aufmerksam, dass mathematisch gesehen dein r schon dem Betrag entspricht. Das kann man ausnutzen, muss man aber auch nicht.



  • @john-0 sagte in Vererbung vs. Komposition:

    P.S. Die Aufgabenstellung verlangt die Nutzung von #include <cmath> und nicht von #include <math.h>. Es ist nur eine Kleinigkeit, aber auch auf das sollte man achten.

    Solche Kleinigkeiten sind mir auch aufgefallen, denn bei zB acos(fx / r) suche ich unwillkürlich nach dem using namespace std. Eigentlich nimmt man eben <cmath> aus der STL.

    Und eine Sache, wo ich jetzt aber nicht weiß, ob es signifikant ist, beim einfachen Quadrieren würde ich statt std::pow(x, 2) lieber einfach(x * x) nehmen.



  • Ich habe jetzt die Klasse nochmal überarbeitet, und die Koordinaten entfernt, da ich ja den Punkt mit der Klasse CPunkt erzeuge. Nun habe ich das Problem, das in den beiden Konstruktoren die Fehlermeldung "Standardkonstruktor in der Klasse CPunkt nicht vorhanden" erscheint. CPunkt ist ja aber vorgegeben, d.h in dieser kann ich nix ändern. Hat da jemand einen Tipp?

    class CPunkt_Polar_V: public CPunkt
    {
    public:
    	CPunkt_Polar_V();
    	CPunkt_Polar_V(double x, double y, double z);
    	void getCoordinates_Polar(double& pPhi, double& pRho, double& pr);
    
    private:
    	double Phi;
    	double Rho;
    	double r;
    };
    
    #include "CPunkt_Polar_V.h"
    #include "CPunkt.h"
    #include <cmath>
    
    
    CPunkt_Polar_V::CPunkt_Polar_V() :Rho(0), Phi(0), r(0)
    {}
    
    CPunkt_Polar_V::CPunkt_Polar_V(double fx, double fy, double fz)
    {
    	r = sqrt(pow(fx, 2) + pow(fx, 2));
    	Phi = atan2(fx, fy);
    	Rho = acos(fy / r);
    }
    
    void CPunkt_Polar_V::getCoordinates_Polar(double& pPhi, double& pRho, double& pr)
    {
    	pPhi = Phi;
    	pRho = Rho;
    	pr = r;
    }
    


  • Du musst den Konstruktor halt aufrufen.

    CPunkt_Polar_V::CPunkt_Polar_V(double fx, double fy, double fz)
       : Punkt(fx, fy, fz)  // <---- hier!
    {
       ...
    }
    

    D.h. bei Polar-Punkt ist ja ein Punkt und somit musst du als erstes den Punkt-Konstruktor aufrufen.



  • Warum muss ich hier den Konstruktor aufrufen? Bei Vererbung bin ich noch nicht so fit...



  • @jand61 sagte in Vererbung vs. Komposition:

    Warum muss ich hier den Konstruktor aufrufen? Bei Vererbung bin ich noch nicht so fit...

    Es muss immer der Konstruktor der Basisklasse ausgeführt werden, entweder der Defaultkonstruktor (das wird implizit gemacht) oder ein ein angepasster wie in Deinem Fall.



  • okay...also habe ich dann durch den Konstruktoraufruf in der abgeleiteten Klasse Zugriff auf die Attribute der Basisklasse, könnte also mit diesen innerhalb der abgeleiteten Klasse arbeiten? Verstehe ich das richtig?
    Und in jedem Konstruktor(außer dem Standardkonstruktor) muss der jeweilige Konstruktor der Basisklasse explizit aufgerufen werden?



  • @jand61 sagte in Vererbung vs. Komposition:

    okay...also habe ich dann durch den Konstruktoraufruf in der abgeleiteten Klasse Zugriff auf die Attribute der Basisklasse, könnte also mit diesen innerhalb der abgeleiteten Klasse arbeiten? Verstehe ich das richtig?

    Nein, das hängt davon ab, wie Du die Member deklarierst. Es gibt public, private und protected. Letzteres erlaubt den Zugriff nur von abgeleiteten Klassen aus, bei private geht das nicht. Beim Konstruktur geht es darum, dass der geerbte Teil korrekt initialisiert wird.

    Beispiel wie man mit protected auf die Member der Basisklasse zugreifen kann bzw. dadurch die Notwendigkeit von Get Funktionen eliminiert.

    class Base1 {
    private:
        int x;
    public:
        virtual ~Base1() {};
        Base1 (int i) : x(i) {};
        virtual int getX () const {return x;}
    };
    
    class Derived1 : public Base1 {
    private:
        int y;
    public:
        Derived1 (int i1, int i2) : Base1 (i1), y (i2) {}
        int getY () const {return y;}
        virtual int compute () {
            return getX() + y;
        }
    };
    
    class Base2 {
    protected:
        int x;
    public:
        virtual ~Base2() {};
        Base2 (int i) : x(i) {}
    };
    
    class Derived2 : public Base2 {
    protected:
        int y;
    public:
        Derived2 (int i1, int i2) : Base2(i1), y(i2) {}
        virtual int compute () {
            return Base2::x + y;
        }
    };
    
    

    Und in jedem Konstruktor(außer dem Standardkonstruktor) muss der jeweilige Konstruktor der Basisklasse explizit aufgerufen werden?

    Sobald man die Basisklasse nicht über den Standardkonstruktor initialisieren will, muss man einen Konstruktor explizit in der abgeleiteten Klasse aufrufen.


  • Mod

    Du kannst dir Vererbung so vorstellen, dass die Kindklasse das gleiche wie die Elternklasse ist, plus die Sachen die in der Kindklasse stehen. Es gibt also einen Teil der Kindklasse, der die Elternklasse ist. Und dieser Teil muss natürlich auch korrekt initialisiert werden. Sonst wäre ja die Gesamtklasse nicht korrekt initialisiert.

    Ich finde die Aufgabenstellung in dieser Hinsicht etwas ungünstig. Es werden zwar die technischen Aspekte gelehrt, aber offensichtlich kam das tiefere Verständnis zu kurz, was Vererbung bedeutet.