Vererbung (Fehlermeldung)



  • Moin moin,

    ich versuche eine Klasse CSpieler von der Klasse CCharacter erben zu lassen.
    Wenn ich es kompilieren will bekomme ich folgende Fehlermeldung:
    In constructor CSpieler::CSpieler():
    error: no matching function for call to CCharacter::CCharacter()
    note: candidates are: CCharacter::CCharacter(std::string)
    note: CCharacter::CCharacter(const CCharacter&)

    Hier der Quelltext:

    CSpieler.h

    #ifndef CSPIELER_H
    #define CSPIELER_H
    
    #include "CCharacter.h"
    
    /*
                * *** Erbt von CCharacter *** *
    */
    
    class CSpieler : public CCharacter
    {
        public:
            // Membervariablen
    
            // Membermethoden
            CSpieler();
            virtual ~CSpieler();
    
    };
    
    #endif // CSPIELER_H
    

    CSpieler.cpp

    #include "CSpieler.h"
    #include "CCharacter.h"
    #include <string.h>
    #include <iostream>
    
    using namespace std;
    
    CSpieler::CSpieler()
    {
    
    }
    
    CSpieler::~CSpieler()
    {
        //dtor
    }
    

    CCharacter.h

    #ifndef CCHARACTER_H
    #define CCHARACTER_H
    
    #include <string.h>
    #include <iostream>
    using namespace std;
    
    class CCharacter
    {
        protected:
            // Membervariablen
            string m_Name;         // Name des Charakters
            int m_HealthyPoints;        // Energie (HP)
    
        public:
            // Membermethoden
            CCharacter(string name);    // Erweiterter Konstruktor für Namenseingabe
            virtual ~CCharacter();      // Std. Destruktor
    
            void setName(string name);
            void setHealthyPoints();
            string getName();
            int getHealthyPoints();
    
            void print();
    
    };
    
    #endif // CCHARACTER_H
    

    CCharacter.cpp

    #include "CCharacter.h"
    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    CCharacter::CCharacter(string name)
    {
        // Standart-Werte initialisieren
        setName(name);
        setHealthyPoints();
    
    }
    
    void CCharacter::setName(string name)
    {
        m_Name = name;
    }
    
    string CCharacter::getName()
    {
        return m_Name;
    }
    
    void CCharacter::setHealthyPoints()
    {
        m_HealthyPoints = 400;
    }
    
    int CCharacter::getHealthyPoints()
    {
        return m_HealthyPoints;
    }
    
    void CCharacter::print()
    {
        cout << "Name: " << m_Name << endl;
        cout << "HP:   " << m_HealthyPoints << endl;
    }
    

    habs auch schon versucht mit CSpieler::CSpieler() : CCharacter
    aber das hat auch nicht viel gebracht^^

    Über Tipps wär ich sehr dankbar^^ Komme hier grade echt nicht weiter, weil ich auch irgendwie nicht verstehe was falsch sein soll... Hatte eigendlich nie Probleme bis ich versucht hab die Quellcodes in Header und Cpp Dateien aufzusplitten^^ 😕



  • Du erbst von CCharacter. Die abgeleitete Klasse muss in ihrem ctor/vor ihrem ctor-Aufruf den ctor von CCharacter aufrufen. Normalerweise würde der default-ctor verwendet. Da Du aber in CCharacter einen neue ctor definiert hast, fällt der default-ctor weg. Übrig bleibt nur Dein ctor mit Argument string. Das Kann der Compiler aber nicht selbst aufrufen.

    Lösungen:

    1. CCharacter einen Standard-ctor (:= ohne Argumente) verpassen
    2. Den CCharacter-ctors im ctor der abgeleiteten Klasse aufrufen


  • Die Idee der Klasse CCharacter einen STd. Konstruktor zu geben hatte ich auch shcon. Nur dann bekomme ich gleich 10 Errormeldungen^^

    -> undefined reference to 'vtable for CCharacter'
    -> undefined reference to 'CCharacter::~CCharacter()'

    und das ganze dann halt 10 mal...

    Ausser ich verstehe das mit dem Std. Konstruktor falsch^^ Habe der Klasse CCharacter einfach jetzt die Zeilen:

    CCharacter();
    

    hinzugefügt

    In der Cpp

    CCharacter::CCharacter()
    {
    }
    


  • nein du musst in der CSpielerklasse per initailisierungsliste den konstruktor von CCharacter aufrufen

    CSpieler::CSpieler()
    : CCharacter("lol")
    {
       // ...
    }
    

  • Mod

    Das liegt daran, dass du angibst, dass du einen eigenen Destruktor hast, diesen aber nirgends definierst.



  • Nach dem löschen des Destruktors ging es 🙂

    Alles klar Problem ist damit gelöst, danke für die Antworten 👍



  • Obwohl ein Problem gibt es doch noch zum Thema Vererbung.

    Klasse main.cpp

    CSpieler spieler();
    spieler.print();
    
    return 0;
    

    Durch die Vererbung sollte es doch jetzt möglich sein, die print()-Methode aus der Klasse CCharacter aufzurufen 😕 Nur leider schmeisst mein Compiler hier ein Fehler:

    -> error: request for member print in spieler which is of non-class type CSPieler()

    Muss ich die print Methode jetzt überschreiben? Dann hätte doch die Vererbung hier garkeinen Sinn^^ Da ich ja (bis jetzt zumindest) noch keine anderen EIgenschaften habe die ich ausgeben möchte?


  • Mod

    CSpieler spieler();
    

    Das ist eine Funktionsdeklaration.



  • Mh ja stimmt aber selbst wenn ich es so mache, meldet mein compiler den selben Fehler:

    CCharacter *pSpieler;
    pSpieler = new CSpieler;
    pSpieler.print();
    
    return 0;
    


  • Bestimmt nicht den selben, aber einen ähnlichen. Hier hast du kein Objekt, sondern einen Zeiger, den du erstmal dereferenzieren mußt (per (*pSpieler).print(); oder pSpieler->print(); ).

    Aber was hindert dich daran, einfach eine lokale Variable anzulegen?

    CSpieler spieler;
    spieler.print();
    
    return 0;
    


  • Nichts oO 😃 lol Ja doch jetzt geht es mit

    CSpieler spieler;
    spieler.print();

    Hab wohl zu lange mit Java programmert ohne was mit Cpp zwischendurch zu machen xD
    Denn ich muss bzw. kann ja auch CCharacter so initialisieren:

    CCharacter character("Name");
    character.print();
    

    Nun dacht ich, wenn ich ein Objekt erzeuge ohne Patrameter muss zumindest die leere Angabe dabeistehen:

    CCharacter character();
    ...
    

    Bin es nämlich so gewohnt (von Java her):

    CCharacter character = new CCharacter();
    


  • Und wenn Du new benutzt, ist das auch in Ordnung. Wenn Du es nicht benutzt, aber eben nicht.



  • So. Hoffe das ist jetzt alles so richtig^^ Wollte nur nochmal fragen ob das so "richtiger" Code ist^^ bzw. ob man das auch wirklich so schreiben würde^^ Gibt ja immer schönen und nicht so schönen Code^^

    CCharacter.h:

    // Konstruktoren
    CCharacter();
    CCharacter(string name);
    

    CSpieler.h, erbt von CCharacter

    CSpieler();
    CSpieler(string name)
    

    CCharacter.cpp

    CCharacter::CCharacter() {}
    CCharacter::CCharacter(string name)
    {
       setName(name);
       set...
    }
    

    CSpieler.cpp

    CSpieler::CSpieler() {}
    CSpieler::CSpieler(string name) : CCharacter(name)
    {
    
    }
    

    Brauche ich die leeren (standart?) Konstruktoren jetzt überhaupt?^^ Oder kann ich die auch einfach weg lassen? 😕



  • Prinzipiell ist es deine Entscheidung, ob du einen namenlosen Charakter bzw. Spieler zulassen willst. Wenn du sicher gehen willst, daß neue Figuren nur mit Name erzeugt werden können, lässt du sie weg.


Anmelden zum Antworten