Gleiche Funktion in verschiedenen Klassen aufrufen.



  • Hi liebe Gemeinde.

    Vereinfachtes Beispiel:
    Ich hab zwei Klassen ClassA und ClassB. Beide besitzen die Funktion print(). Jetzt möchte ich NUR EINE Variable anlegen, die entweder von Typ ClassA oder ClassB ist und die printfunktion darüber aufrufen.

    so etwa in der Art:

    #include <iostream>
    
    using namespace std;
    
    class classA
    {
    	public:
    		int a1;
    
    	classA()
    	{
    		a1 = 21;
    	}
    
    	void print()
    	{
    		std::cout << "a1=" << a1 << std::endl;
    	}
    };
    
    class classB
    {
    	public:
    		int b1;
    
    	classB()
            {
    		b1 = 31;
    	}
    
    	void print()
    	{
    		std::cout << "b1=" << b1 << std::endl;
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	int i = 0;
    
    	void *myClass;
    
    	switch(i)
    	{
    		case 0:	myClass = new classA(); break;
    		case 1: myClass = new classB();break;
    	}
    
    	myClass->print();
    }
    

    Könnt ihr mir da auf den rechten Weg helfen?

    Gruß Tobi



  • tobi_from_HH schrieb:

    Hi liebe Gemeinde.

    Vereinfachtes Beispiel:
    Ich hab zwei Klassen ClassA und ClassB. Beide besitzen die Funktion print(). Jetzt möchte ich NUR EINE Variable anlegen, die entweder von Typ ClassA oder ClassB ist und die printfunktion darüber aufrufen.

    Könnt ihr mir da auf den rechten Weg helfen?

    Gruß Tobi

    Das Stichwort, das Du brauchst ist virtual.

    mfg Martin



  • Wie soll das genau gehen? Ich hab ja keine abgeleitete Klasse.



  • tobi_from_HH schrieb:

    Wie soll das genau gehen? Ich hab ja keine abgeleitete Klasse.

    Das geht halt nur mit abgeleiteten Klassen.



  • Einfach beide Klassen von einer abstrakten Basisklasse mit Printfunktion ableiten



  • TNA schrieb:

    Einfach beide Klassen von einer abstrakten Basisklasse mit Printfunktion ableiten

    Dann kann ich aber nicht auf die Daten der erbenden Klasse zugreifen.


  • Mod

    tobi_from_HH schrieb:

    TNA schrieb:

    Einfach beide Klassen von einer abstrakten Basisklasse mit Printfunktion ableiten

    Dann kann ich aber nicht auf die Daten der erbenden Klasse zugreifen.

    Deswegen ja auch virtual!



  • tobi_from_HH schrieb:

    TNA schrieb:

    Einfach beide Klassen von einer abstrakten Basisklasse mit Printfunktion ableiten

    Dann kann ich aber nicht auf die Daten der erbenden Klasse zugreifen.

    Warum nicht? Natürlich geht das. Mußt halt casten. Das hättest Du aber mit deiner void* Lösung auch machen müssen. Hier kannst Du sogar typsicher casten (Stichwort dynamic_cast)

    mfg Martin



  • tobi_from_HH schrieb:

    TNA schrieb:

    Einfach beide Klassen von einer abstrakten Basisklasse mit Printfunktion ableiten

    Dann kann ich aber nicht auf die Daten der erbenden Klasse zugreifen.

    Auf b1 bzw. a1 kannst du dann nicht zugreifen, das ist richtig. Das ist dynamisch aber nicht (bzw. kaum) möglich.*
    Wenn du Zugriff brauchst, schreib dir auch eine virtuelle get-Funktion. Wenn die Member von verschiedenen Typen sind, musst du downcasten. Das ist aber fast immer ein Zeichen von schlechtem Design, also solltest du dann dein Design überdenken.

    * Edit: Um das deutlicher auszudrücken: Es ist unmöglich einfach eine Variable zu erstellen, die ist entweder a oder b und dann einfach so behandeln, als wär sie eine von beiden.


  • Mod

    mgaeckler schrieb:

    Warum nicht? Natürlich geht das. Mußt halt casten. Das hättest Du aber mit deiner void* Lösung auch machen müssen. Hier kannst Du sogar typsicher casten (Stichwort dynamic_cast)

    Warum ein typisches Zeichen für Designfehler als Vorschlag? Hier spricht doch alles für eine abstrakte Basisklasse. Kein Grund, hier irgendwelche dynamic_casts einzubauen.



  • SeppJ schrieb:

    mgaeckler schrieb:

    Warum nicht? Natürlich geht das. Mußt halt casten. Das hättest Du aber mit deiner void* Lösung auch machen müssen. Hier kannst Du sogar typsicher casten (Stichwort dynamic_cast)

    Warum ein typisches Zeichen für Designfehler als Vorschlag? Hier spricht doch alles für eine abstrakte Basisklasse. Kein Grund, hier irgendwelche dynamic_casts einzubauen.

    Vielleicht habe ich die Anforderung falsch verstanden. Ich dachte da an sowas:

    class base
    {
    	public:
    	virtual void print() = 0;
    };
    
    class derivedA : public base
    {
    	public:
    	double myDblValue;
    
    	deriveA()
    	{
    		myDblValue = 3.14;
    	}
    
    	virtual void print()
    	{
    		cout << myDblValue;
    	}
    }
    
    class derivedB : public base
    {
    	public:
    	int myIntValue;
    
    	deriveA()
    	{
    		myIntValue = 3;
    	}
    
    	virtual void print()
    	{
    		cout << myIntValue;
    	}
    }
    
    int main( void )
    {
    	base *ptr;
    
    	ptr = new ......;
    
    	ptr->print();
    
    	derivedA *aPtr = dynamic_cast<derivedA *>ptr;
    
    	if( aPtr )
    		cout << aPtr->myIntValue;
    
    	derivedB *bPtr = dynamic_cast<derivedB *>ptr;
    
    	if( bPtr )
    		cout << aPtr->myDblValue;
    
    	return 0;		
    }
    

    Das ist jetzt kein compilierbarer Code, man möge mir daher Tippfehler verzeihen. Es soll nur demonstrieren wie man mit dynamic_cast oder virtuellen Funktionen das selbe Ergebnis erzielen kann. Selbstverständlich ist in diesem konkreten Beispiel die virtuelle Funktion vorzuziehen, aber die Aufgabenstellung war ja nicht spezifisch genug um abschliesend urteilen zu können, ob dynamic_cast nicht auch eine sinnvolle Option wäre.

    Ich finde der Einsatz von dynamic_cast ist nicht sofort ein Zeichen für einen Designfehler.

    mfg Martin



  • aber die Aufgabenstellung war ja nicht spezifisch genug um abschliesend urteilen zu können, ob dynamic_cast nicht auch eine sinnvolle Option wäre.

    Ich finde der Einsatz von dynamic_cast ist nicht sofort ein Zeichen für einen Designfehler.

    Wenn kein GUTER Grund gegen die Verwendung von virtuellen Funktionen spricht, dann schon 😉
    Wenn ein solcher, wie gesagt GUTER, Grund nicht angegeben wurde, dann halte ich es daher auch für nicht angebracht dynamic_cast zu erwähnen.

    OK, von mir aus in einem Nebensatz dass das auch möglich wäre. Aber primär sollten bei der Fragestellung erstmal virtuelle Funktionen erwähnt werden.



  • hustbaer schrieb:

    OK, von mir aus in einem Nebensatz dass das auch möglich wäre. Aber primär sollten bei der Fragestellung erstmal virtuelle Funktionen erwähnt werden.

    Richtig, deswegen war ja auch virtual mein erster Vorschlag.

    mfg Martin



  • Upps, sorry, übersehen 🙂



  • dynamic_cast funktioniert nur bei Zeigern oder Referenzen auf Klassen. Einen void* kann man mit dynamic_cast nicht casten.



  • tntnet schrieb:

    dynamic_cast funktioniert nur bei Zeigern oder Referenzen auf Klassen. Einen void* kann man mit dynamic_cast nicht casten.

    Richtig, das ist ein weiterer Grund, warum der Threadesteller gar nicht um eine Basisklasse herumkommt. Bei seiner Idee mit einem void * hätte er nämlich 'nen normalen cast benutzen müssen und sowas ist immer gefährlich und sollte nur mit bedacht benutzt werden.

    mfg Martin


Log in to reply