Problem mit Konstruktor der Basisklasse



  • Ich habe ein Problem mit dem Konstruktor meiner Basisklasse oder besser gesagt mit den erbenden Klassen der Basisklasse. Die Basisklasse hat einen Konstruktor, der ein Argument erwartet. Die erbende Klasse besitzt einen Konstruktor, der auch ein Argument benötigt, jedoch ein vollkommen anderes. Wenn ich das ganze nun kompilieren möchte, dann erhalte ich folgende Fehlermeldung:

    error C2512: 'BaseClass' : no appropriate default constructor available

    Der Code sieht kurz zusammengefasst so aus:

    BaseClass:

    class BaseClass
    {
    public:
    	BaseClass(EineKlasse* Klasse);
    	~BaseClass();
    protected:
    	EineKlasse* m_Klasse;
    };
    
    BaseClass::BaseClass(EineKlasse* Klasse)
    : m_Klasse(Klasse)
    {
    	//...
    }
    
    BaseClass::~BaseClass()
    {
    	m_Klasse = NULL;
    };
    

    AbgeleiteteKlasse:

    class AbgeleiteteKlasse : public BaseClass
    {
    public:
    	AbgeleiteteKlasse(EineAndereKlasse* AndereKlasse);
    	~AbgeleiteteKlasse();
    protected:
    	EineAndereKlasse* m_AndereKlasse;
    };
    
    AbgeleiteteKlasse::AbgeleiteteKlasse(EineAndereKlasse* AndereKlasse)
    : m_AndereKlasse(AndereKlasse)
    {
    	//...
    }
    
    AbgeleiteteKlasse::~AbgeleiteteKlasse()
    {
    	m_AndereKlasse = NULL;
    };
    

    Wenn ich in der Basisklasse nun zusätzlich zu dem vorhandenen Konstruktor noch einen Default-Konstruktor hinzufüge, dann funktioniert es. Ist das der einzige Weg in meiner Situation? Beinträchtigt der Default-Konstruktor das Verhalten der Klasse? Bei Google habe ich noch folgendes gefunden:

    If you have a constructor for your base class which takes a few arguments, you should have your derived class call the base class'constructor. Like this:
    
    .cpp file
    
    CSomeDerivedClass::CSomeDerivedClass(int argument) : CSomeClass(argument)
    

    Das lässt sich bei mir leider nicht anwenden, da die abgeleitete Klasse die "EineKlasse" in der Basisklasse nicht kennt und sie in der zweiten Klasse nicht vorhanden ist bzw. gebraucht wird.

    Das mag nun ein wenig kompliziert erklärt sein, aber ich hoffe trotzdem, dass ihr mir helfen könnt 😉



  • Wenn EineKlasse* als CTOR Argument nicht benötigt wird, übergib doch 0.
    Simon



  • Eine andere Möglichkeit, als einen zweiten ctor oder das übergeben von 0 ist, dass du ein default Argument dazufügst. (Kommt schlussendlich auf etwa das gleiche raus, ist imo aber passender)

    class BaseClass
    {
    public:
        explicit BaseClass(EineKlasse* Klasse = 0);
        ~BaseClass();
    protected:
        EineKlasse* m_Klasse;
    };
    

    Mach dann den ctor gleich noch explicit .



  • Alles klar, vielen Dank für die Hilfe. Ich habe nun die Lösung von Drakon genommen, da sie mir eleganter erscheint.



  • Wenn du für die Abgeleitete Klasse das Verhalten der Basisklasse (in diesem Fall deren Konstruktor-signaturen) verändern musst, sieht das arg nach einem Designfehler aus. Wenn die Basisklassenfunkionalität in der abgeleiteten Klasse nicht benötigt wird, dann ist das Ableiten eine Fehlentscheidung. Wenn nur ein Teil der Basisklassenfunktionalität benötigt wird, solltest du diesen Teil in eine extra Klasse auslagern und sowohl deine bisherige Basisklasse als auch die abgeleitete Klasse von der neuen Klasse ableiten.

    Wenn du uns verrätst was du erreichen willst, können wir dir vielleicht beim Design etwas weiter helfen.



  • Scheint mir auch ein Design fehler zu sein, wobei das ganze nicht so einfach ist. Ich könnte der Basisklasse auch einfach einen Default-Konstruktor geben und die benötigte Klasse meiner Hauptfunktion übergeben. Das sähe dann so aus:

    void WINAPI EineFunktion(class xKlasse *XK)
    {
    	Basisklasse BKlasse;
    	BKlasse.Main(XK->BenoetigteKlasse);
    }
    

    Klassen wie xKlasse befinden sich in einem SDK (Software Development Kit), sodass sich diese nicht ohne Weiteres ändern lassen. Außerdem ist das Projekt eine DLL, die dann über einen Hook in die entsprechende Applikation injiziert wird. Gehookt wird eine Funktion, die die gewünschte Klasse (xKlasse) als Paramter besitzt, sodass man damit arbeiten (bsp. über Unterklassen) kann.

    Die benötigte Klasse würde ich dann in der Main-Funktion den erbenden Klassen zugänglich machen, wobei ich dann nicht kontrollieren könnte, ob sie noch aktuell ist, was ich ja automatisch mache, wenn ich jedesmal ein neues Objekt der Basisklasse erstelle, wenn etwas in EineFunktion (Funtkion des Hooks) passiert. Ich könnte dann natürlich die benötigte Klasse immer wieder den entsprechenden Funktionen als Parameter übergeben, aber das ist - soweit ich das verstanden habe - nicht wirklich Sinn der objektorientenden Programmierung. Was mir zum Schluss hin noch einfällt ist, dass ich sowieso immer ein neues Objekt der erbenden Klasse in der Main-Funktion erstelle und ich die benötigte Klasse darüber einfach übergeben und dann im Dekonstruktor wieder NULL setze kann. Das würde dann so aussehen:

    void WINAPI EineFunktion(class xKlasse *XK)
    {
    	Basisklasse BKlasse;
    	BKlasse.Main(XK->BenoetigteKlasse); //BenoetigteKlasse vom Typ aKlasse
    }
    
    void Basisklasse::Main (aKlasse *BenoetigteKlasse)
    {
    	if (BenoetigteKlasse != NULL)
    	{
    		ErbendeKlasse EK(BenoetigteKlasse);
    		EK.MachWas();
    	}
    }
    

    Falls irgendwer eine Idee hat, wie man das ganze verbessern könnte, dann immer her damit.


Anmelden zum Antworten