Zugriff auf Methoden abgeleiteter Klassen die allerdings nicht in der Basisklasse definiert sind mit Basisklassenzeiger
-
und sowas wie templates zur laufzeit gibbet net?
-
nein
mein alter post is hier auf seite 1 der letzte von mirhier, damit du nich suchen must:
aber schau dir mal diese funktion an:
HRESULT QueryInterface( REFIID riid, LPVOID *ppvObj );
das is ne methode in directx.
erster parameter isn einfacher string, in der du den namen des gewünschten interface eingibst, und der 2. parameter ist ein zeiger auf das interface, welches du in zukunft verwenden willst. Der returnwert gibt true zurück, wenn die klasse für die queryinterface aufgerufen wurde von dem im 2. parameter übergebenen interface abgeleitet wurde.das wäre zb:
XComBase* a= new XComGuiWin32(); XComGuiBase* b; a->queryInterface("XComGuiBase",static_cast<void**>(&b)); b->InitCommonControls();
ich würde aber statt returnwert ne gute alte exception benutzen
-
was macht denn da der static_cast? Und was muss dann die QueryInterface Methode machen?
Sry, aber deinen Thread finde ich nicht nur einen anderen von dir, aus 3 Beiträgen zur Einschränkung der Vererbung...
Gruß Sebastian.
-
keinen thread, der post den ich hier gepostet+gepastet hab, hab ich gemeint...
queryInterface funktioniert in etwa wie ein dynamic cast,intern kenn ich den code nicht, ein dynamic_cast kanns nich sein,aber ich vermute, dass es so aussieht://bei statischer polymorphie: IUnknown{ public: virtual void queryInterface(std::string Type,void** Pointer){ throw("cannot cast);//iunknown hat keine baseclass,man kann davon also nicht casten } }; class Derived:public IUnknown{ public: virtual void queryInterface(std::string Type,void** Pointer){ if(Type=IUnknown){ *Pointer=this; } else { IUnknown::queryInterface(Type,Pointer); } } };
ich gebe keine garantie, dass dies vollständig oder richtig ist, dass sind halt die überlegungen aus 5 minuten vorm nudeltopf stehen
ps:der static_cast ist da, um von dem zeiger nach void** zu casten.
-
Schau dir das Component Object Model an. Die Erklärungen von otze sind ja grauenhaft.
-
naja ich sehe grade das das ganze für mich gar nix bringt... Du machst dort ja nix weiter als nen Objekt. Das Objekt mache ich ja auch schon über meinen XComBase Zeiger das ist ja kein Problem. Es geht drum das ich Zugriff brauche auf meine anderen Klassen über diesen pointer oder habe ich irgendwas verpasst?!
-
Also in dem beispiel wird ja nur das Objekt erzeugt, auf das der Pointer zeigen soll. Dazu habe ich bei mir ja in jeder Dll eine Funktion, die das übernimmt:
Beispiel Win32 - Gui dll:
extern "C" __declspec (dllexport) void XExport (HINSTANCE hdll, XComBase** ptr_base, XGuiMessageSystem* ptr_message) { *ptr_base = new XComGuiWin32 (ptr_message); }
Also es geht hier gar nicht um das Objekt, was erzeugt werden muss. Das es vorher erzeugt werden muss ist klar, aber das erledigt eh der Manager, von welchem zuerst die Methode registerPlugin aufgerufen werden muss
#ifdef WIN32 strcpy ((char*)dllname, (char*)"dll"); strcat ((char*)dllname, (char*)"\\XWin32.dll"); *mglog << "Betriebsystem erkannt auf >>WINDOWS<<" << endl; if (!(hDll = LoadLibraryEx (dllname, NULL, 0))) { *mglog << "Error binding Dll to application's address space" << endl; } /* Zeiger auf die richtige Klasse initialisieren und dann im Pluginvektor abspeichern, damit die Anwendung darauf zugreifen kann */ GUI_PLG gplg = NULL; gplg = (GUI_PLG) GetProcAddress (hDll, "XExport"); gplg (hDll, &ptr_base, ptr_message); plgStack.insert(make_pair (counter, ptr_base));
Erst hiernach sollen die Methoden des Plugins zur Verfügung stehen.Da ich aber mit einem XComBase* auf beispielsweise ein XWin32 Objekt zugreife, bekomme ich die Methoden auf die weise nicht mehr; sie sind in XComBase ja nicht definiert.
Bitte sagt mir jetzt wie die oben genannte QueryInterfacemethode mir da helfen kann....
Gruß Sebastian
-
du übergibst queryinterface das neue interface,welches du benutzen willst, und queryinterface richtet dir je nach klasse alles ein, was gebraucht wird.
query interface macht nämlich eigentlich sogar noch viel mehr, da es sogar in manchen klassen dazu befähigt ist, das objekt selber zu ändern, je nachdem welches interface benutzt wird.also, du hast ein interface x und y.
x zeigt auf ein objekt, du willst nun aber, dass y auf das objekt zeigtx->doSth(); x->queryInterface("class",y); //y zeigt nun auf ein objekt y->doSth();
queryinterface geht eigentlich sogar noch einen stück weiter,aber das führt hier zu weit.
ansonsten benutzt du einfach deinen dynamic cast^^
-
ich weiss nicht ob ich es vielleicht nicht verstanden habe, aber:
mein Zeiger zeigt auf das richtige Objekt! nur wenn ich mit nem A* auf B zeige, und dann A* auf ein Objekt von B zeigt, habe ich noch nix gewonnen. Auf die Methoden von B kann ich auch dann nur zugreifen, wenn sie in A definiert sind, und das ist das problem.
-
auch wenn sie nicht so heisst meine QueryInterface methode sieht wahrscheinlich so aus:
unsigned long XComManager::registerPlugin (unsigned long plgID, XComBase* ptr_base, XGuiMessageSystem* ptr_message) { HMODULE hDll = (HMODULE) NULL; char* dllname = new char [100]; static int counter = 0; // GUI - Plugin laden if (plgID == PLG_GUI) { *mglog << "Plugin erkannt auf PLG_GUI" << endl; #ifdef WIN32 strcpy ((char*)dllname, (char*)"dll"); strcat ((char*)dllname, (char*)"\\XWin32.dll"); *mglog << "Betriebsystem erkannt auf >>WINDOWS<<" << endl; if (!(hDll = LoadLibraryEx (dllname, NULL, 0))) { *mglog << "Error binding Dll to application's address space" << endl; } /* Zeiger auf die richtige Klasse initialisieren und dann im Pluginvektor abspeichern, damit die Anwendung darauf zugreifen kann */ GUI_PLG gplg = NULL; gplg = (GUI_PLG) GetProcAddress (hDll, "XExport"); gplg (hDll, &ptr_base, ptr_message); plgStack.insert(make_pair (counter, ptr_base)); *mglog << "Neues Element in map eingefügt mit ID " << counter << endl; counter++; /* eigentlich Aufgabe der Anwendung */ dynamic_cast<XComGuiBase*>(ptr_base)->xCreate (ptr_pref, 0); dynamic_cast<XComGuiBase*>(ptr_base)->xMain (ptr_pref); #else //Lade Linuxpluigin #endif } // Render - Plugin laden else if (plgID == PLG_RENDER) { } return 0; }
Die XExport funktion für den fall kennt ihr ja schon....
-
fluxy schrieb:
ich weiss nicht ob ich es vielleicht nicht verstanden habe, aber:
mein Zeiger zeigt auf das richtige Objekt! nur wenn ich mit nem A* auf B zeige, und dann A* auf ein Objekt von B zeigt, habe ich noch nix gewonnen. Auf die Methoden von B kann ich auch dann nur zugreifen, wenn sie in A definiert sind, und das ist das problem.
ach ich gebs auf, du wirst es nicht kapieren, dass danach das übergebe(ein anderes!!!!) Interface auf B zeigt
-
ein anderes???? hmmm wie jetzt?
-
XComBase* a= new XComGuiWin32(); XComGuiBase* b; a->queryInterface("XComGuiBase",static_cast<void**>(&b)); b->InitCommonControls();
das poste ich hier jetzt zum 3. mal wenn dus jetzt nich verstehst, solltest dein projekt canceln
-
wieso soll ich ein Projekt canceln, nur wenn es mal Probleme gibt:
Also aus der QueryInterface methode entnehme ich, dass sie in dem Fall wie du sie grade aufrufst, ne exception wirft (weil du sie nicht mit IUnknown aufgerufen hast). Ist das so der Sinn???
-
das wirft keine exception, es wirft nur ne exception, wenn du a) ein interface übergibst, dass nicht compatibel mit der klasse ist, oder b) die klasse kein interface hat(in dx ist die einzige klasse die kein interface hat IUnknown, wovon jede andere klasse abgeleitet ist
also nochmal das ganze prinzip:
//kurzformat^^ class IUnknown;//hat die methode queryinterface, die wenn sie aufgerufen wird, ne exception wirft class derived:public IUnknown;//überschreibt queryInterface, sodass bestimmte typen akzeptiert werden,ansonsten wird das queryinterface von IUnknown benutzt class derived2:public derived;//überschreibt queryInterface von derived,auch hier werden wieder bestimmte interfaces akzeptiert, und wenns nich klappt, wird queryInterface von derived aufgerufen
ist also bei mir ein klassischer fall von rekursion, es wird schrittweise durch die vererbungen durchgegangen, und getestet, ob das übergebe Interface damit kompatibel ist.
-
okay jetzt habe ich das verstanden. allerdings hast du in deinem Beispiel als 2. Paramter für QueryInterface einen static_cast angegben der als Ziel nen XComGuiBase benötigt, also muss die anwendung trotzdem alle klassen kennen oder???
otze schrieb:
XComBase* a= new XComGuiWin32(); XComGuiBase* b; a->queryInterface("XComGuiBase",static_cast<void**>(&b)); b->InitCommonControls();
Die Frage war ja wie ich genau darauf verzichten kann...
-
du woltlest keinen dynamic cast, den static cast kannst du nicht verhindern,und ein static_cast ist wirklich nicht schlimm.
-
na1a eigentlich wollte ich jeden Cast auf die Zielklasse verhindern... obs jetzt nen static_cast oder nen dynamic_cast ist, ist mir eigentlich scheiss egal...
-
das wird kein cast auf die zielklasse, sodnern ein cast auf void**, und ich würde gerne mal erfahren, wo du ne klasse void** hast
-
XComGuiBase* b; a->queryInterface("XComGuiBase",static_cast<void**>(&b));
was machst du denn da? Du erzeugst zusätzlich zu dem Zeiger auf XComBase einen Zeiger auf XComGuiBase und übergibst diesen dem static_cast operator. Du sagst ihm lediglich dass er daraus nen void** machen soll, aber deine Quelle ist dein XComGuiBase pointer....