Mehrfachvereerbung



  • Hallo,

    mir ist hier etwas nicht ganz klar:

    Angenommen ich habe 4 Klassen:

    Klasse0, die Mutter aller klassen, rein virtuell,
    Klasse1, leitet sich von Klasse 0 ab, ebenfalls virtuell,
    Klasse2, leitet sich von Klasse 0 ab, ebenfalls virtuell,
    Klasse4, benötigt die virtuellen Methoden von Klasse1 und Klasse2.

    Wenn ich jetzt in main z.B. ein Array aus Objekten der Klasse0 anlege, und Objekte der Klasse4 dort hineinspecihern will, bekomme ich Fehlermeldungen a lá

    "Klasse1.Methode() ist kein Element von Klasse0"
    "Klasse2.Methode() ist kein Element von Klasse0"

    Klasse1 und 2 sind doch aber auch gleichzeitig Klasse0?
    Dem Klasse0 Array dürfte das doch egal sein? Habe ich hier einen Denkfehler? Muss ich irgendwie besonders casten?

    Problemstellung:
    Ich möchte mehrere Interfaces je nach Bedarf in Klasse4 implementieren, so eine Art Listener Konzept.

    Viele Grüße!



  • BjarneS_aus_P schrieb:

    Klasse0, die Mutter aller klassen, rein virtuell,

    Es gibt keine rein virtuellen Klassen. rein virtuell können nur Memberfunktionen sein. Basisklassen hingegen können nur virtuell, nicht aber rein virtuell sein. Eine virtuelle Basisklasse ist eine Basisklasse von der virtuell abgeleitet wird. Eine Basisklasse die nur rein virtuelle Memberfunktionen enthält nennt man häufig Protokoll-Klasse.

    Also: Was meinst du mit rein virtuell? Basisklasse von der virtuell geerbt wird? Basisklasse von der virtuell geerbt wird und die nur rein virtuelle Memberfunktionen enthält? Oder Basisklasse die nur rein virtuelle Memberfunktionen enthält, von der aber normal abgeleitet wird?

    Und zeig bitte mal etwas Code.



  • Ich sitze leider nicht an meinem Heimrechner, daher muss ich Code aus dem Kopf ziehen, sollte zur Verdeutlichung aber reichen denke ich.

    Also: Was meinst du mit rein virtuell?

    Klasse0 verfügt eigentlich momentan nur über das Klassenkonstrukt:

    class Klasse0
    {};
    

    Klasse1 und 2 verfügen über rein virtuelle Methoden (public wg. Test):

    class Klasse1 : public Klasse0
    {
    public:
    	virtual void methode1()=0;
    };
    
    class Klasse2 : public Klasse0
    {
    public:
    	virtual void methode2()=0;
    };
    

    Jetzt kommt Klasse4 (eigentlich 3, naja egal):

    class Klasse4 : public Klasse1, Klasse2
    {
    public:
    	Klasse4();
    	~Klasse4();
    	void methode1();
    	void methode2();
    };
    
    Klasse4::Klasse4()
    {
    	...
    }
    
    Klasse4::~Klasse4()
    {
    	...
    }
    
    void Klasse4::methode1()
    {
    	...
    }
    
    void Klasse4::methode2()
    {
    	...
    }
    

    Und natürlich main:

    Klasse0* AllClasses[10];
    AllClasses[0]=new Klasse4();
    AllClasses[0]->methode1();
    AllClasses[0]->methode2();
    

    Ich bin Anfänger, und da sind wahrscheinlich tausend Fehler drin. Konstruktive Kritik wäre schön 😃

    Ps:
    Header Dateien etc.pp. sollten korekt eingebunden sein.

    Vielen Dank!



  • BjarneS_aus_P schrieb:

    Also: Was meinst du mit rein virtuell?

    Klasse0 verfügt eigentlich momentan nur über das Klassenkonstrukt:

    class Klasse0
    {};
    

    Das ist einfach eine leere Klasse. Die ist weder virtuell noch sonstwas. Das ist auch genau der Grund für den Fehler. Du sagst in deinem Code, dass alle deine Klasse eine spezielle Form der Klasse0 sind und demzufolge alle Klassen auch das Klasse0-Interface erfüllen. Dieses Interface ist aber leer. Demzufolge kannst du über eine Klasse0-Referenz natürlich auch keine Methoden aufrufen.



  • Hi,

    wenn du einen Zeiger Klasse0* hast, dann stellt der Compiler dafür auch nur die Methoden der Klasse 0 bereit - den Zeiger musst du also erst casten.

    Statt

    AllClasses[0]->methode1();
    

    also

    ((Klasse1*)AllClasses[0])->methode1();
    

    (Klammern nicht vergessen, -> hat Vorrang.)

    Bin auch erst Anfänger, und ich hab in einem tut gelesen, vor allem Anfänger setzen das Konzept der Vererbung viel zu oft ein - eventuell ist es sinnvoller mit Attributen zu arbeiten als solche undurchsichtigen Konstrukte zu schaffen...

    rabbit



  • RabbitsDad schrieb:

    Statt

    AllClasses[0]->methode1();
    

    also

    ((Klasse1*)AllClasses[0])->methode1();
    

    Das ist ein Hack. Mehr nicht. Du bekämpfst das Sympton nicht die Ursache (und das auch noch auf ungeprüfte Art und Weise).
    Beim Programmieren geht es nicht darum solange rum zu pfriemeln bis der Compiler irgendwann die Klappe hält.



  • Im Prinzip müsste ich also genau umgekehrt vorgehen, Klasse0 erbt dann quasi von Klasse1 und 2, ich reiche die virtuellen Methoden dann sozusagen durch bis zur konkreten Implementierung in Klasse4.

    Das wäre aber nicht das was ich brauche. Denn auf diese Weise würde Klasse0 alle virtuellen Methoden übernehmen, und damit auch Klasse4. Klasse4 sollte aber beispielsweise nur methode1 kennen, so dass diese implementiert werden muss.

    Im Prinzip speichere ich also später die Obermenge von Klasse1 und 2 in einer zentralen Struktur, allerdings weiß ich nicht wie dann die base-Klasse dieser beiden Klasse auszusehen hat...:(

    Oder muss ich hier Templates benutzen?



  • Kann ja sein, dass das mit Linux nicht passiert wäre, aber solche "Hacks" werden z. B. in der MFC ganz regelmäßig verwendet.

    GetDlgItem der CDialog Klasse liefert einen void*-Pointer denn man dann entsprechend dem Element (CEdit, CButton,...) castet.

    rabbit



  • RabbitsDad schrieb:

    Kann ja sein, dass das mit Linux nicht passiert wäre, aber solche "Hacks" werden z. B. in der MFC ganz regelmäßig verwendet.

    GetDlgItem der CDialog Klasse liefert einen void*-Pointer denn man dann entsprechend dem Element (CEdit, CButton,...) castet.

    rabbit

    Ich kenne das Konzept leider nur in Java. Wenn ich da will, das ein Button auf einen Event hört, muss ich dort den entsprechenden Listener implementieren. Dann hört der Button aber auch nur auf diese Events, die ich entsprechend der implementierten Methoden zu behandeln habe. Es ist kein Problem, mehrere Listener zu implementieren.


Anmelden zum Antworten