Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 16

Thema: Vererbung und Konvertierung

  1. #1
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42

    Vererbung und Konvertierung

    Hi, hab wieder mal ne Frage

    Also ich hab eine Liste von Klassen, die natürlich alle gleich sind, wo aber jede eine andere "Tochter"-Klasse von aKlasse enthalten soll.

    Die Klassen aus der Liste können diese Tochter-Klassen dann also ganz einfach als aKlasse behandeln, aber jetzt kommt dass Problem mit der Konvertierung.

    Soweit ich weiß, kann ich eine Methode in der Tochter-Klasse, die es in aKlasse nicht gibt, von den Listen-Klassen nicht benutzen, da es für sie ein Objekt der aKlasse ist. Es sollen trotzdem alle eine andere Funktion update() enthalten, also definiere ich diese Methode schon in der aKlasse, und überlade (heißt das so?) sie dann in jeder Tochter-Klasse.

    Meine Frage ist jetzt, ob, wenn ein Objekt einer Tochter-Klasse als aKlasse bekannt, beim ausführen überladener Methoden die alte Mehode aus aKlasse, oder die neue, überladene, Methode ausgeführt wird.

    (Ansonsten könnte ich versuchen dass ganze über Sinals und Slots zu regeln, wobei connect() in den Tochter-Klassen ausgeführt wird, da nur diese wissen von welchem Typ sie sind, aber eigentlich hab ich es nicht vor.)

    EDIT:
    Hm, der Text ist unlogisch. Wenn alles was ich gesagt hab stimmt, dann geht es logisch nicht. Also gehe ich mal davon aus, dass mein Text nen Fehler hat
    Um die Situation noch genauer zu beschreiben ein bisschen code:

    Die Klasse, die in der Liste verwendet wird:
    Code:
    class Item
    {
      private:
        Item( aKlasse obj );
        ~Item();
        aKlasse* objekt;
        // Der Rest ist unwichtig...
    };
    Methode(n) der Klasse:
    Code:
    Item::Item( aKlasse obj )
    {
      objekt = obj;
      objekt->update();
      // Und weiteres...
    }
    Und hier wird ein Item der Liste angefügt:
    Code:
    void neFunktion()
    {
      list = new QPtrList<Item>;
      list->append( new Item( new aKlassenTochterEins ) );
      list->append( new Item( new aKlassenTochterZwei ) );
      list->append( new Item( new aKlassenTochterDrei ) );
      // und so weiter
    }
    Hoffe mal das reicht
    Die Methode update() aus den aKlassenTöchtern benutzt Variablen, die nur die Klassen selber enhalten, also wenn die Methode in aKlasse ausgeführt würde, gäbe es ein paar nicht existierende Variablen, deshalb ist mein Text unlogisch.

    Also ne neue Frage:
    Wird im Konstruktor von Item die Methode aKlasse::update(), oder die Methode aKlassenTochter::update() ausgeführt?
    Geändert von Firebird (04-11-2003 um 19:21 Uhr)

  2. #2
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486

    Re: Vererbung und Konvertierung

    Original geschrieben von Firebird

    Soweit ich weiß, kann ich eine Methode in der Tochter-Klasse, die es in aKlasse nicht gibt, von den Listen-Klassen nicht benutzen, da es für sie ein Objekt der aKlasse ist. Es sollen trotzdem alle eine andere Funktion update() enthalten, also definiere ich diese Methode schon in der aKlasse, und überlade (heißt das so?) sie dann in jeder Tochter-Klasse.

    Meine Frage ist jetzt, ob, wenn ein Objekt einer Tochter-Klasse als aKlasse bekannt, beim ausführen überladener Methoden die alte Mehode aus aKlasse, oder die neue, überladene, Methode ausgeführt wird.
    Du deklarierst die Methode update in der Oberklasse als virtual (am besten pure virtual,damit vemeidest du gleich von Anfang an Object-Slicing).
    In den Unterklassen überschreibst du diese Methode (achte auf die korrekt Signatur),und wenn du jetzt mit einem Pointer/einer Referenz auf ein Oberklasseobjekt zugreifst,was aber in Wirklichkeit ein Unterklasseobjekt ist,dann wird die Methode der Unterklasse aufgerufen.

  3. #3
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Ah, THX, das klingt gut
    Ich hab mich bisher noch nie mit Virtual etc. beschäftigt, wie genau benutzt man es?
    "pure virtual bool update();", und dann in den Tochter-Klassen auch noch so, oder nur "bool update();" ?

    Hatte grad mein Posting da oben nochmal bearbeitet, aber ich glaub, dass war nicht nötig

  4. #4
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von Firebird

    "pure virtual bool update();", und dann in den Tochter-Klassen auch noch so, oder nur "bool update();" ?
    pure ist kein Schlüsselwort.
    Bsp.
    Code:
    class Oberklasse
    {
    public:
        virtual void update() {/* Leer oder default Implementierung*/ }
        virtual void update_2() = 0;//Pure Virtual,es gibt keine Implementierung
    };
    
    class Unterklasse : public Oberklasse
    {
    public:
        void update() {/* Implementierung von update für Unterklasse */}
        void udate_2() {/* /* Implementierung von update_2 für Unterklasse */*/ }
    };
    Wenn eine Methode einmal als virtual deklarriert wurde,so ist sie es in allen Unterklassen auch,man hätte in Unterklasse vor update und update_2 noch virtual davor schreiben können,ist aber redundant.
    Wenn eine Methode als pure virtual deklarriert ist (siehe update_2 in Oberklasse),dann ist es nicht möglich von Oberklasse eine Instanz zu erzeugen (Zeiger von Oberklasse sind aber möglich).
    class Oberklasse ist abstract.
    Jede Klasse,die von Oberklasse erbt,muß wenn sie nicht auch abstract sein will,update_2 implementieren.

  5. #5
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Hab das jetzt mal probiert, bekomme aber folgende Fehler:

    unterklasse.h:41: error: base class `Oberklasse' has incomplete type
    unterklasse.h:41: warning: `Unterklasse' has virtual functions but non-virtual destructor
    Ich weiß nicht ob der erste Fehler was hiermit zu tun hat, weil ich nicht so ganz weiß was mit Typ gemeint ist.
    Aber wozu brauche ich einen virtuellen Destruktor?

  6. #6
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von Firebird
    Hab das jetzt mal probiert, bekomme aber folgende Fehler:
    unterklasse.h:41: error: base class `Oberklasse' has incomplete type
    Du hast wahrscheinlich nur eine Forwardeclaration von Oberklasse im Header von Unterklasse bekannt.
    Aber das reicht nicht,binde den Header von Oberklasse ein.


    unterklasse.h:41: warning: `Unterklasse' has virtual functions but non-virtual destructor

    Aber wozu brauche ich einen virtuellen Destruktor?
    Das ist so eine Faustregel,das jede Klasse die virtuelle Funktionen hat,auch eine virtuellen Destruktor braucht.
    Denn sonst wird,wenn du delete auf einen Zeiger der Oberklasse aufrufst,aber eigentlich ein Objekt der Unterklasse ist,nur der Destruktor der Oberklasse aufgerufen -> Speicherleck.

  7. #7
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Original geschrieben von wraith
    Du hast wahrscheinlich nur eine Forwardeclaration von Oberklasse im Header von Unterklasse bekannt.
    Aber das reicht nicht,binde den Header von Oberklasse ein.


    Hm... hab folgendes da:

    Code:
    // Includes
    #include <oberklasse.h>
    
    // Klassen
    class Oberklasse;
    Das ist so eine Faustregel,das jede Klasse die virtuelle Funktionen hat,auch eine virtuellen Destruktor braucht.
    Denn sonst wird,wenn du delete auf einen Zeiger der Oberklasse aufrufst,aber eigentlich ein Objekt der Unterklasse ist,nur der Destruktor der Oberklasse aufgerufen -> Speicherleck.
    Ok, dann mach ich dat mal (obwohl ich ansonsten - noch - absolut keine Zeigerobjekte lösche).

  8. #8
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von Firebird
    Hm... hab folgendes da:

    Code:
    // Includes
    #include <oberklasse.h>
    Code:
    // Klassen
    class Oberklasse;
    In oberklasse.h wird ja irgendwie sowas stehen
    Code:
    class Oberklasse
    {
    
    };
    Die Forwarddeklaration ist dann überflüssig.

    Btw. für deine Header,die in deinem Verzeichniss liegen,mit include "" arbeiten.


    Ok, dann mach ich dat mal (obwohl ich ansonsten - noch - absolut keine Zeigerobjekte lösche).
    Es bringt dir keinen Nachteil,und für den nächsten C++ Standard ist sowieso geplant,daß eine Klasse mit virtuellen Funktionen automatisch eine virtuellen Destruktor bekommt.Noch müssen wir da selber drandenken.
    Aber dir ist klar,daß du für Polymorphie (virtual...),mit Zeiger bzw. Referenzen arbeiten mußt.

  9. #9
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Original geschrieben von wraith
    In oberklasse.h wird ja irgendwie sowas stehen
    Code:
    class Oberklasse
    {
    
    };
    Die Forwarddeklaration ist dann überflüssig.

    Btw. für deine Header,die in deinem Verzeichniss liegen,mit include "" arbeiten.
    Jo, dachte ich eigentlich auch, aber wenn ich nur die Header-Dateien einbinde (egal ob mit </> oder "/") bringt mir der Compiler (fast in jeder Datei) überall wo ich so eine Klasse verwende nen Syntax Error.
    Ob das was damit zu tun hat, dass ich in Datei klassea.h die Datei klasseb.h, und in Datei klasseb.h die Datei klassea.h einbinde (was eigentlich eine unendliche Verschachtelung ist, die vom Compiler aber anscheinend ignoriert wird), weiß ich noch nicht so genau...

    Vielleicht kommt der error ja da her, dass "class oberklasse;" nicht reicht, sondern auch der Inhalt enthalten sein muss. Das heißt ich bin wieder mal bei dem Problem mit den nicht funktionierenden Includes (Wie bei meinem letzten Thread hier im Forum...).

    Aber dir ist klar,daß du für Polymorphie (virtual...),mit Zeiger bzw. Referenzen arbeiten mußt.
    Ich arbeite grundsätzlich (naja meistens) nur mit Zeigern... die sind einfach praktischer - auch wenn man sie löschen muss.

  10. #10
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Original geschrieben von Firebird
    Jo, dachte ich eigentlich auch, aber wenn ich nur die Header-Dateien einbinde (egal ob mit </> oder "/") bringt mir der Compiler (fast in jeder Datei) überall wo ich so eine Klasse verwende nen Syntax Error.
    Dann passt was mit den Headern nicht.
    Poste mal die genau Fehlermeldung und wenn möglich den Header.


    Ob das was damit zu tun hat, dass ich in Datei klassea.h die Datei klasseb.h, und in Datei klasseb.h die Datei klassea.h einbinde (was eigentlich eine unendliche Verschachtelung ist, die vom Compiler aber anscheinend ignoriert wird), weiß ich noch nicht so genau...
    Wäre möglich.
    Reicht es denn nicht, wenn du im jeweiligen anderen Header nur die forward declaration der Klasse hast?

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  11. #11
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Wäre möglich.
    Reicht es denn nicht, wenn du im jeweiligen anderen Header nur die forward declaration der Klasse hast?
    Dass hab ich jetzt mal ausprobiert, und es klappt!!
    Komisch is nur, dass jetzt auch der andere Fehler und die Warnung von oben weg sind.

    Die Warnung müsste eigentlich noch kommen, da der Destructor immernoch "non-virtual" ist, aber die kommt nicht...

    THX dann mal... ich hoffe mal jetzt kommen keine Fehler mehr dazu

    Jetzt grad eben ist mir auch noch eingefallen, dass die Verschachtelung von KDevelop verhindert wird:
    Code:
    #ifndef KLASSE_H
    #define KLASSE_H
    Also ist dass Problem wirklich gelöst...

  12. #12
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Sieht so aus, als wäre doch noch nicht alles gelöst.

    Mein Problem ist, wenn ich in Unterklasse ein Objekt vom Typ HauptKlasse (die Haupt-Anwendung, die alle möglichen Zeiger etc. enthält, die ich im Programm brauche - in diesem Fall ein Zeiger auf ein Objekt von QSettings - aber nicht durch ne Menge funktionen weiterreichen will..) verwende, dass in OberKlasse definiert ist, bekomme ich folgenden Fehler:

    unterklasse.cpp:51: error: invalid use of undefined type `struct Hauptklasse'
    oberklasse.h:28: error: forward declaration of `struct Hauptklasse'
    Und zwar für jede Stelle in unterklasse.cpp, wo ich das Objekt benutze einmal.

    Warum hält der Compiler Hauptklasse für eine Struktur, obwohl es eine Klasse ist!?

    Wenn ich jetzt aus oberklasse.h die "forward declaration" "class Hauptklasse;" entferne, bekomme ich natürlich erstmal Syntax Error, und wenn ich "#include "hauptklasse.h"" einfüge (mich wundert, dass dann kein Syntax Error mehr kommt, da KDevelop eigentlich verhindert hat, dass Header-Dateien mehrmals inkludiert bzw. beachtet werden - hab ich ja geschrieben - aber hauptklasse.h schon vorher inkludiert wurde.), bin ich wieder beim gleichen Fehler wie oben (mit dem Unterschied, dass ich die Warnung mittlerweile weg gemacht hab):

    unterklasse.h:41: error: base class `oberklasse' has incomplete type
    In Zeile 41 steht "class unterklasse : public oberklasse". Ich denk mal, dass - weil ich von Vererbung kaum Ahnung hab - in oberklasse noch etwas wichtiges fehlt, damit ich es vererben kann. Und nochwas: werden nur Öffentliche (Public) Funktionen und Variablen vererbt, oder auch Private?
    Mich würde es schon sehr weiterbringen, wenn ich wüsste was mit "type" gemeint ist (Ist der Typ denn nicht "oberklasse" ?).

  13. #13
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Du musst in unterklasse.cpp den Header von Hauptklasse inkludieren.

    Im Header reicht die Forward Declaration, die du durch den Oberklasse Header bekommst, aber bei Benutzung der Klasse muss ihre gesamte Deklaration bekannt sein und dazu inkludiert man den Header.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  14. #14
    Registrierter Benutzer
    Registriert seit
    28.10.2003
    Beiträge
    42
    Ok, das scheint wiedermal zu funktionieren, aber das nächste Problem ist schon wieder da:

    Wenn ich Oberklasse::FunktionAusOberklasseVonOberklasse() ausführe, ist die Funktion nicht deklariert.....

    Ich glaub bevor ich an meinem Programm weitermache les ich erstmal nochn C++-Buch - 3000 errors am Tag machen mich verrückt
    Vorallem die Vererbung hab ich wohl noch net so ganz begriffen..

  15. #15
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Original geschrieben von Firebird
    Wenn ich Oberklasse::FunktionAusOberklasseVonOberklasse() ausführe, ist die Funktion nicht deklariert.....
    Das sollte in Unterklasse wirklich nicht auftreten, sehr eigenartig.
    Bist du sicher, dass die Methode in oberklasse.h wirklich deklariert ist und auch nicht private ist?

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •