Typ der Variable erst zur Laufzeit zuweisen?



  • Ich habe folgendes Problem: Ich möchte ein Gerät (LockIn)ansteuern und nenne dies mal m_LockIn. Jetzt habe ich aber zwei verschiedene Geräte sagen wir A und B.

    Jetzt wähle ich zur Laufzeit aus ob ich A oder B nehmen möchte. Jetzt brauche ich ein

    Lockin = new GeraetA
    

    das funktionert aber auch nur wenn ich Lockin als

    GeraetA Lockin
    

    definiert habe.

    Wie mache ich das dann so dass LockIn sowohl den Type GeraetA als auch GeraetB haben kann?

    Matthias



  • Basisklasse erstellen und von dieser ableiten. Dann kannst Du in den Basiszeiger A und B stecken



  • Knuddlbaer schrieb:

    Basisklasse erstellen und von dieser ableiten. Dann kannst Du in den Basiszeiger A und B stecken

    Mir fehlt gerade die Intuition was du meinst. Ich müsste ja im Konstruktor die abgeleitete Klasse ändern, oder was meinst du genau?

    Matthias



  • class Base{
    
    };
    
    class Typ1 : public Base{
    
    };
    
    class Typ2 : public Base{
    
    };
    
    Base *pVariant;
    

    Irgendwann zur laufzeit:

    pVariant = new Typ1;
    

    oder

    pVariant = new Typ2;
    


  • Dazu aber noch virtuelle Funktionen :):

    class Base{
        virtual void DoSomething()
        {
            cout << "Ich bin die Basis-Klasse" << endl;
        }
    };
    
    class Typ1 : public Base{
        virtual void DoSomething()
        {
            cout << "Ich bin Typ 1" << endl;
        }
    };
    
    class Typ2 : public Base{
        virtual void DoSomething()
        {
            cout << "Ich bin Typ 2" << endl;
        }
    };
    
    Base *pVariant;
    if ( bla )
        pVariant = new Typ1();
    else
        pVariant = new Typ2();
    pVariant->DoSomething();
    


  • Wofür die virtuellen Funktionen? Beide Geräte haben nicht vollständig identische Funktionen.

    Ich habe Klassen der Geräte die ich aber eigentlich nicht ändern möchte. Geht dann auch folgendes?

    #include "GPIBDevices.h"
    
    class CLockIn
    {
    public:
    	CLockIn(void);
    	~CLockIn(void);
    	bool Connected;
    };
    
    class LockInSRS : public CLockIn, public GPIB_SRSLockIn
    {
    };
    
    class LockInSRSRF : public CLockIn, public GPIB_SRSRFLockIn
    {
    };
    

    Ich bekomme dann mit folgendem Code

    if (theApp.Settings.lockin.getLockInType() == RF) {
    		theApp.LockIn = new LockInSRSRF;
    	}
    	else if (theApp.Settings.lockin.getLockInType() == LF) {
    		theApp.LockIn = new LockInSRS;
    	}
    	int board = theApp.Settings.lockin.getBoard();
    	int address = theApp.Settings.lockin.getAddress();	
    	BOOL result = theApp.LockIn->CreateLockIn(board, address);
    

    den Fehler

    error C2039: 'CreateLockIn': Ist kein Element von 'CLockIn'

    Warum nicht ?

    Matthias



  • Genau für sowas würdest du virtuelle Methoden benötigen - du hast ein gemeinsames Interface für unterschiedliche Klassen.



  • pospiech schrieb:

    Wofür die virtuellen Funktionen? Beide Geräte haben nicht vollständig identische Funktionen.

    Das ist auch in Ordnung, aber wenn der Typ zur Kompilier-Zeit nicht feststeht und du es über Vererbung löst, kannst du nur dir Schnittmenge der Funktionen nutzen. Ansonsten musst du die Typinformationen bewahren und mit if's rumhantieren.

    pospiech schrieb:

    error C2039: 'CreateLockIn': Ist kein Element von 'CLockIn'

    Ist halt nicht in der Klasse 'CLockIn' deklariert 😕



  • Wofür die virtuellen Funktionen? Beide Geräte haben nicht vollständig identische Funktionen.

    Fragen wir anderst:

    Wenn beide Geräte nicht identisch sind, wie möchtest Du diese später unterscheiden ? In Deiner Variablen kann ja A oder B stehen. IRgendeine Idee hast Du da ja sicherlich schon gehabt bevor Du auf die Idee gekommen bist A ODER B in ne Variable zu stecken.



  • Badestrand schrieb:

    pospiech schrieb:

    Wofür die virtuellen Funktionen? Beide Geräte haben nicht vollständig identische Funktionen.

    Das ist auch in Ordnung, aber wenn der Typ zur Kompilier-Zeit nicht feststeht und du es über Vererbung löst, kannst du nur dir Schnittmenge der Funktionen nutzen. Ansonsten musst du die Typinformationen bewahren und mit if's rumhantieren.

    Das heißt das was ich wollte geht nicht bzw nur dann wenn ich für alles virtuelle Funktionen definiere?

    Matthias



  • beschreib doch erstmal genau was du willst 🤡

    e: oder willst du einfach die (überschriebenen?) Funktionen aus "CLockIn" dynamisch entweder in TypA oder TypB benutzen?



  • Badestrand schrieb:

    beschreib doch erstmal genau was du willst 🤡

    e: oder willst du einfach die (überschriebenen?) Funktionen aus "CLockIn" dynamisch entweder in TypA oder TypB benutzen?

    Eigentlich möchte ich das eine variable beliebige Klassen annehmen kann. Das konzept einer dritte Klasse mit virtuellen Funktionen verstehe ich, ist mir aber im Moment zu aufwendig. Da ist es erstmal einfacher zwischen zwei Variablen mit ifs zu unterscheiden.

    Matthias



  • Naja, wenn die Variable einen beliebigen Typ aufnimmt, woher willst Du denn dann wissen was in der variable stekct und wie es zu verwenden ist ?

    Ich kann zwar nen Kaffee und nen Toast schwarz Servieren, aber die Geräte sind dazu schon unterschiedlich zu verwenden ;o)



  • Also willst du quasi sowas?:

    class Katze
    {
        void fauchen();
    };
    
    class Hochhaus
    {
        int baueStockwerk( int hoehe, int stahltraeger );
    };
    
    variable v;
    if ( bla )
        v = new Natze();
    else
        v = new Hochhaus();
    
    ...
    
    if ( v is Katze )
        v.fauchen();
    else if ( v is Hochhaus )
        v.baueStockwerk( 7, 189 );
    


  • Ja das war meine ursprüngliche Idee.

    Matthias



  • Da musst du hässlicherweise mit einem Zeiger auf void arbeiten.
    Beispiel:

    #include <iostream>
    #include <ctime>
    using namespace std;
    
    class Katze
    {
    public:
    	void sagMiau()
    	{
    		cout << "Miau\n";
    	}
    };
    
    class Hochhaus
    {
    public:
    	void baueStockwerk(int hoehe)
    	{
    		cout << "Stockwerk der Hoehe "<< hoehe << " gebaut\n";
    	}
    };
    
    namespace wirrwarr
    {
    	void *was_auch_immer;
    	bool ist_katze;
    }
    
    void kockolores()
    {
    	if (wirrwarr::ist_katze)
    	{
    		Katze *k = static_cast<Katze *>(wirrwarr::was_auch_immer);
    		k->sagMiau();
    	}
    	else
    	{
    		Hochhaus *h = static_cast<Hochhaus *>(wirrwarr::was_auch_immer);
    		h->baueStockwerk(12);
    	}
    }
    
    int main()
    {
    	srand(time(0));
    	wirrwarr::ist_katze = (rand()%2 == 0);
    
    	if (wirrwarr::ist_katze)
    		wirrwarr::was_auch_immer = new Katze;
    	else
    		wirrwarr::was_auch_immer = new Hochhaus;
    
    	kockolores();
    }
    

    Du solltest aber auf jeden Fall über eine Klassenhierarchie nachdenken. Bei Unterklassen ist übrigens ein virtueller Destruktor wichtig, falls Objekte dieser Klassen über einen Basisklassenzeiger vom Heap gelöscht werden sollen.



  • void * schrieb:

    Bei Unterklassen ist übrigens ein virtueller Destruktor wichtig ...

    Der virtuelle Destruktor muss natürlich für die Basisklasse definiert sein.



  • pospiech schrieb:

    Ja das war meine ursprüngliche Idee.

    Matthias

    Dann war das eine schlechte Idee !! 😉
    "Wer" (also welche Funktion, welches Objekt, ....) soll denn etwas mit einem "Ding" anfangen können, dass "alles und nichts" kann ?

    Sorry, aber das sieht mir nach "Ich habe keine Lust, mir jetzt Gedanken zu machen und hoffe, das mit Flexibilisierung auf später verschieben zu können" aus. (no offense)

    Wenn Du zwei Objekte hast, die NICHTS miteinander zu tun haben, dann gibt es auch keine sinnvolle Funktion, die Du mit dem Einen wie mit dem Anderen aufrufen kannst.
    WENN sie aber doch etwas Gemeinsames haben, kommt man dem mit virtuellen Funktionen meist ganz gut bei (vielleicht nicht immer, aber ich behaupte mal, dass Anfänger nie ein derartiges Szenario haben).

    Also mein Tipp: Trenne die Dinge entweder ganz oder verbinde sie sinnvoll, dann bringt Dein Programm auch was. 😃

    Gruß,

    Simon2.



  • naja ich glaub (wenn ich mir die Bezeichnung der Klassen anschaue) haben die klassen die er über die selber variable verwalten will schon gemeinsamkeiten haben... ich denke mal das er nich ganz verstanden hat was wir wollen bzw. was es mit virtuellen funktionen mit verwanden klassen auf sich hat...

    Erklär doch mal was die Klassen "lockxxxx" machen, und welche gemeinsamkeiten sie haben....

    Grüße


Anmelden zum Antworten