Interface bzw Class Problem



  • Hallo liebes C++ Forum,
    Ich bin neu in diesem Forum und auch noch am Anfang von C++,
    Ich bin derzeit am rum probieren und gerade bin ich bei Interfaces bzw vererbungen generell angekommen, mein aktuelles Problem ist folgendes:
    Ich habe ein Interface erstellt und sie einfach mal LolChampion genannt (mir ist sonst nicht besseres eingefallen in dem moment ;D, für die Leute die Lol nicht kennen, ein Champion ist kein Character).
    Dieses wollte ich in einer Seperaten Klasse auslagern, jedoch meckert dann die Klasse in die ich das Interface implementieren möchte rum das er die class nicht finden kann, paste ich den Code des Interfaces in die Klasse hinein in die ich es Implementieren möchte geht es jedoch einwandfrei, ich hoffe ihr könnt mir helfen 🙂

    LolChampion.cpp

    #include <iostream>
    
    class LolChampion {
    
    public:
    	// Empty virtual destructor for proper cleanup
    	virtual ~LolChampion() {}
    	virtual std::string getName() = 0;
    	virtual std::string getLore() = 0;
    	virtual void load() = 0;
    };
    
    };
    

    Mecker Klasse

    class Kalista : public LolChampion {
    public: {
    
    };
    };
    


  • Du brauchst "Header Files".



  • Und wie darf ich mir das vorstellen? ich möchte ja am ende das interface einfach in einer anderen datei auslagern o_O, wieso benötige ich dafür einen header? bin noch nicht ganz vertratut damit.


  • Mod

    Ein Header ist ein Interface in einer anderen Datei.

    Das heißt konkret, du packst alles, was die Schnittstelle der Klasse ausmacht in eine eigene Datei:
    lolchampion.h

    #ifndef LOL_CHAMPION_H
    #define LOL_CHAMPION_H
    
    class LolChampion {
    
    public:
        // Empty virtual destructor for proper cleanup
        virtual ~LolChampion();
        virtual std::string getName() = 0;
        virtual std::string getLore() = 0;
        virtual void load() = 0;
    };
    
    #endif
    

    Die konkreten Implementierungen in Quellcodedateien:

    lolchampion.cpp

    #include "lolchampion.h"
    
    LolChampion::~LolChampion() {}
    

    Noch eine Anmerkunggen, die nicht direkt zur Frage gehört:
    Kurze Funktionen, wie deinen Destruktor hier, in eine eigene Quellcodedatei auszulagern, lohnt kaum. Die kann man dann auch direkt in den Header schreiben:

    #ifndef LOL_CHAMPION_H
    #define LOL_CHAMPION_H
    
    class LolChampion {
    
    public:
        // Empty virtual destructor for proper cleanup
        virtual ~LolChampion() {}
        virtual std::string getName() = 0;
        virtual std::string getLore() = 0;
        virtual void load() = 0;
    };
    
    #endif
    

    Das ist in diesem Fall besonders schön, da man die zugehörige Quellcodedatei komplett einspart.



  • Leftwitch2 schrieb:

    Mecker Klasse

    class Kalista : public LolChampion {
    public: {
    
    };
    };
    

    Hast du das genauso drin? Da steckt ein {}; zu viel drin, d.h.:

    class Kalista : public LolChampion {
    public:
    };
    

    Du solltest also einen Fehler wie " error: expected unqualified-id before ‘{’ token " bekommen. Genauer Code / exakte Fehlermeldungen helfen immer weiter.

    Vermutlich hat das nix mit deinem Problem zu tun und du hast einfach anderen Code gepostet als du wirklich hast. Das ist immer blöd.

    Bzgl. Header-Aufteilung kamen ja schon andere Antworten.



  • @wob ja, dachte aber das er mit meinem Problem zusammenhängt 🙂 (also zu sagen sagen anders priorisiert)
    @SeppJ danke dir, das ich verständlich, aber heisst das jetzt das ich für jede externe Klasse einen header brauch? oder nur interfaces

    //EDIT

    Ich Scheiter jetzt bei der Anwendung der Klasse ...
    Ich habe die Kalista klasse jetzt dem LolChampion implementieren lassen, dies klappt auch soweit, nun häng ich daran fest wie ich ein LolChampion objekt kriegen kann, mit

    LolChampion chaml = new Kalista()
    

    geht es nicht da spukt er einen Fehler..

    Header:

    #pragma once
    #ifndef LOL_CHAMPION_H 
    #define LOL_CHAMPION_H 
    #include <string>
    class LolChampion {
    
    public:
    	// Empty virtual destructor for proper cleanup 
    	virtual ~LolChampion() {}
    	virtual std::string getName() = 0;
    	virtual std::string getLore() = 0;
    	virtual void load() = 0;
    };
    
    #endif
    

    Kalista Klasse:

    #include "LolChampion.h"
    #include <iostream>
    using namespace std;
    class Kalista : public LolChampion {
    public: 
    	virtual ~Kalista() {
    
    	}
    	virtual std::string getName() const{
    		return "Kalista";
    	};
    	virtual std::string getLore() const {
    		return "Test123";
    	};
    	virtual void load() const { 
    		cout << "Kalista Loaded";
    	};
    
    };
    


  • Und warum zeigst du uns den restlichen Code nicht? Vorallem der in main()...
    Und warum zeigst du uns die exakte Fehlermeldung nicht?

    Beides hilft.

    // edit

    Im gezeigten Code gibt es ein Problem, und zwar gehört const bei Methoden zur Signatur. D. h. std::string Kalista::getName() const überschreibt/implementiert nicht std::string LolChampion::getName() . Das wiederum führt zu Fehlern beim Kompilieren.

    Am besten benutzt du zudem in der abgeleiteten Klasse das override Schlüsselwort.



  • Ich habe die main nicht gesposted, da in der einfach nur im int main() das hier steht:

    LolChampion chaml = new Kalista()
    

    wie ich oben aber auch schon schrieb
    Den Fehler lässt mich Visual Studio nicht kopieren.. da steht sowas "object of abstract class LolChampion is not allowed"



  • Leftwitch2 schrieb:

    Ich habe die main nicht gesposted, da in der einfach nur im int main() das hier steht:

    LolChampion chaml = new Kalista()
    

    Dann steht da halt nur Müll.



  • Sehr hilfreich, solche Kommentare benötigt man nicht, oder möchtest du mir die Aussagekraft erläutern?
    Wenn du ein Problem mit der Fragestellung hast ignoriere den Thread danke.



  • Guck dir diese Zeile nochmal genau an. Du erstellst eine konkrete Instanz deiner abtrakten Klasse LolChampion, was natürlich nicht funktioniert, da ja schließlich abstrakt.
    Du kannst allerdings Zeiger und Referenzen vom Typ dieser Klasse auf Objekte abgeleiteter Klassen zeigen:

    LolChampion *chaml = new Kalista; //ein LolChampion-Zeiger zeigt auf ein Kalista-Objekt
    

    Da new und delete nicht gerne in Reinform gesehen werden, rate ich dir zu Smartpointern:

    std::unique_ptr<LolChampion> = std::make_unique<Kalista>();
    

    Natürlich kannst du das ganze auch ohne dynamischem Anlegen tun, kommt auf den Anwendungsfall an:

    Kalista kal;
    LolChampion *chaml = &kali; //einmal mit zeigern
    LolChampion &qwerty = kali; //und referenzen
    


  • Ui ;D, wieder was gelernt, danke dir, immer wenn du denkst das du die basics vesstanden hast kommt was neues ;DD, wird zeit das mein Buch ankommt 😉



  • Die Frage ist ja auch, ob alle Methoden virtuell sein müssen. Ginge nicht auch sowas:

    #include <string>
    #include <memory>
    
    class LolChampion
    {
       std::string Name_;
       std::string Lore_;
    public:
       LolChampion();
    
       const std::string& name() const { return Name_; }
       void               set_name( const std::string& n ) { Name_ = n; }
    
       ...
    };
    
    std::shared_ptr<LolChampion> make_kalista()
    {
       auto c = std::make_shared<LolChampion>( new LolChampion() );
       c->set_name( "Kalista" );
       c->set_lore( "Peng peng peng" );
       return c;
    }
    

    Zur Erzeugung bietet sich dann natürlich eine Fabrik an, statt konkreter Erzeugerfunktion.


Anmelden zum Antworten