anoniem Geplaatst: 3 juni 2004 Delen Geplaatst: 3 juni 2004 Hallo, Sinds enige tijd ben ik met Visual C++ en OpenGL bezig. Ik hoop dat ik mijn probleem een beetje duidelijk kan uitleggen, want het zit een beetje vreemd. Het probleem: Alle functies die ik moet aanroepen om OpenGL te intialiseren heb ik in de class 'CInit' gezet. Deze class bevat o.a. de functie 'Functions'. Deze functie zorgt ervoor bv. voor keyboard input de functie glutKeboardFunc([i:4c826b9b91]'func keyboard_functie' [/i:4c826b9b91]) wordt aangeroepen. De functie die ik als argument dan glutKeyboardFunc() wil meegeven zit echter in een andere class genaamd 'CInput'. In de main functie heb staan: CInit init; CInput [u:4c826b9b91]input[/u:4c826b9b91]; Maar wanneer ik echter in de functie 'init.Functions' glutKeboardFunc(input.Keyboard) gebruik kent ie de class [u:4c826b9b91]input[/u:4c826b9b91] niet. Nog een beetje schematisch: [code:1:4c826b9b91] class CInit { void Functions() { // hier staan dus de functies om callbacks te registreren glutKeyboardFunc(input.Keyboard); } }; class CInput { void Keyboard(); }; void main() { CInit init; CInput input; init.Functions(); }[/code:1:4c826b9b91] Ik zat te denken om de pointer van ' input' als argument aan init.functions mee te geven. Is dit een goede manier, en zo ja hoe doe ik dit of moet ik dit anders aanpakken? MVGR, René Quote Link naar reactie
anoniem Geplaatst: 3 juni 2004 Auteur Delen Geplaatst: 3 juni 2004 Ik vind het wel een risico op init en input als variabele namen te gebruiken. Lijken wel erg veel op keywords dat zou weleens een probleem kunnen geven. Verder zie ik zo snel niet wat het probleem zou kunnen zijn. Quote Link naar reactie
anoniem Geplaatst: 4 juni 2004 Auteur Delen Geplaatst: 4 juni 2004 Zou me niks verbazen indien input een gereserveerd woord is in VC++... Quote Link naar reactie
anoniem Geplaatst: 4 juni 2004 Auteur Delen Geplaatst: 4 juni 2004 Ik zat al aan pointer te denken, maar dat werkt ook niet helemaal zoals ik verawcht had. [code:1:ad9cd1a756] class CInit { void Functions(void (* Keyboard_functie)(void)) { // hier staan dus de functies om callbacks te registreren glutKeyboardFunc(KeyBoard_functie); } }; class CInput { void Keyboard(); }; void main() { void (*pKeyboard)(void); // pointer naar functie CInit init; CInput control; pKeyboard = control.Keyboard; // pointer wijst naar functie init.Functions(pKeyboard); // pointer naar functie als argument }[/code:1:ad9cd1a756] Nu krijg ik echter een error: error C2440: '=' : cannot convert from 'void (__thiscall CInput::*)(void)' to 'void (__cdecl *)(void)' There is no context in which this conversion is possible Doe ik iets verkeert met de pointer? Quote Link naar reactie
anoniem Geplaatst: 4 juni 2004 Auteur Delen Geplaatst: 4 juni 2004 Wat je doet is het volgende: [code:1:10cfef00df]pKeyboard = control.Keyboard; // pointer wijst naar functie [/code:1:10cfef00df] pKeyboard = functie pointer control.Keyboard = een niet statische member functie van een class. Deze pointers zijn totaal verschillend van elkaar vandaar ook de foutmelding: __thiscall = calling conventie voor waarbij een extra "this" variabele wordt bijgehouden (in verband met het object). Je kunt meerdere objecten aanmaken maar natuurlijk moet wel worden bijgehouden welk object het is vandaar de extra variabele __cdecl = standaard calling conventie zonder this variabele. Je kunt deze twee dus niet aan elkaar toewijzen. Wat er dus eigenlijk gebeurd is dat je C en C++ door elkaar heen gebruikt en daardoor treden deze problemen op. Een object (class) heeft een hele andere benadering dan een standaard functie. Je zou het even kort door de bocht zo moeten in de class: void (CInput::*Keyboard functie)() ; oproepen door: (control.*Keyboard functie)(); (controlpointer->*Keyboard functie)(); waarbij controlpointer van het type control* is. Je zou eens moeten kijken naar onderwerpen zoals "virtual functions" en de c++ faq moeten lezen op dit specifieke onderwerp daar staan heel boeiende dingen in: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1 http://www.parashift.com/c++-faq-lite/virtual-functions.html suc6 Quote Link naar reactie
anoniem Geplaatst: 5 juni 2004 Auteur Delen Geplaatst: 5 juni 2004 pfff.. Ik ben nog niet zo bekend met C++ om dit te snappen. Zou je misschien iets speciefieker kunnen vertellen waar ik wat neer moet zetten. iig bedankt voor je reactie.. Quote Link naar reactie
anoniem Geplaatst: 5 juni 2004 Auteur Delen Geplaatst: 5 juni 2004 Ik heb zelf nooit opengl geprogrammeerd, maar na wat rondneuzen blijkt dat het probleem is dat opengl geschreven is voor c en niet het object georienteerde c++. Goed even misschien een korte uitleg over objecten en gewone functie's Een object (ook wel class genoemd) kan in meerdere instantie's (meerdere objecten) aangemaakt worden waarbij ieder aangemaakt object een stukje geheugen ruimte krijgt. Wanneer een functie in zo'n object wordt opgeroepen dan moet natuurlijk wel duidelijk zijn welk object aangesproken moet worden (omdat je meerdere objecten kunt aanmaken) en daarvoor wordt een soort extra variabele gebruikt. Een c functie heeft deze extra variabele niet nodig, omdat deze maar 1 keer in het geheugen geladen kan worden en niet in meerdere instanties voor kan komen. Vandaar dus de foutmelding die je kreeg "cdecl" (standaard c) en "thiscall" (c++) conversie error. Je wilde een functie pointer gelijk maken aan een object pointer en dat gaat niet zoals ik boven heb uitgelegd. Opengl is geschreven voor c. Dat wil zeggen dat de functie's in opengl niet om kunnen gaan met het object georienteerde c++. Even simpel voorgesteld: opengl kent bijvoorbeeld callbacks. Een opengl functie is bijvoorbeeld geschreven om 3 zaken terug te geven: 1. De pointer naar de oproepende functie 2. Een x waarde 3. Een y waarde Zoals je ziet geeft de functie geen variabele mee om het aanroepende object te identificeren alleen maar een pointer naar een functie. Dus weet je nooit welk object (class) de ontvangen waarden moet krijgen. Wat je dan kunt doen is een soort van c++ ontwerp maken die deze zaken weer opvangt zodat je toch met objecten kunt werken, maar dit is geen goede oplossing denk ik omdat je daar veel tijd mee kwijt bent. Je kunt in principe 2 dingen doen: 1. Gebruik maken van een c++ wrapper die tegen opengl praat (dan kun je wel het object georienteerde c++ gebruiker om te programmeren, maar kent natuurlijk wel veel haken en ogen: http://www.nigels.com/glt/ 2. Je programma schrijven in c code. Op de opengl site staan veel verwijzingen naar tutorials die je kunt bekijken: http://www.opengltutorial.co.uk/ bijvoorbeeld. Visual c++ betekent niet dat je in c++ moet programmeren dus je kunt ook gewoon in de c methode werken. Ik hoop dat het nu wat duidelijker is. Quote Link naar reactie
anoniem Geplaatst: 5 juni 2004 Auteur Delen Geplaatst: 5 juni 2004 Bedankt voor je uitleg. Dat met die wrapper lijkt me ook niet echt een goed plan. Ga me dan maar met C verder. Ook nog bedankt voor die link naar opengltutorial.co.uk. Die was ik mijn zoektochten over het internet naar tutorials nog niet tegengekomen en die site ziet er wel duidelijk uit. René Quote Link naar reactie
anoniem Geplaatst: 9 juni 2004 Auteur Delen Geplaatst: 9 juni 2004 Ik heb mijn programma een beetje omgebouwd zodat ik wel classes kan gebruiken. Ik heb de volgende bestanden: main.cpp -> main functie control.cpp -> klasse die keyboard events afhandeld (klasse heet: CControl) camera.cpp -> klasse die camera 'bestuurt' (klasse heet: CCamera) In main.cpp staat: CCamera camera; main() etc..... Nu wil ik echter in een member functie van de CControl klasse een member functie van CCamera aan roepen. Nu is het probleem dat de klasse camera alleen global is in main.cpp en dat deze niet zomaar te bereiken vanuit control.cpp Ik heb gelezen dat je dit met pointers moet doen; dus een pointer naar een member functie. Ik dacht het zelf op deze manier te doen, maar dit werkte niet: [code:1:b89b252688] In header file 'stdafx.h': void (*pMoveCamera)(float speed); in 'camera.cpp': class CCamera { void MoveCamera(float speed) { } }; in 'control.cpp': class CControl { void SpecialKeyboard(int key, int x, int y) { pMoveCamera(0.5); // Hier de member functie aanroepen m.b.v. de pointer } }; in 'main.cpp': CCamera camera main() { pMoveCamera = camera.MoveCamera; } [/code:1:b89b252688] Ik krijg op deze manier de volgende error: cannot convert from 'void (__thiscall CCamera::*)(float)' to 'void (__cdecl *)(float)' Dus weer iets van die calling conventies waar [DarthV] het al over had. Ik kan dus niet de functie pMoveCamera naar de member functie camera.MoveCamera laten wijzen. Hoe moet ik dit dan doen? René Quote Link naar reactie
anoniem Geplaatst: 10 juni 2004 Auteur Delen Geplaatst: 10 juni 2004 Je maakt opnieuw de fout door een standaard functie pointer een pointer naar een member functie te geven van een class. Oplossing: Declareer op de juiste manier: Standaard functie pointer: void (*pMoveCamera)(float speed); Pointer naar een member functie declaratie: void ([b:b4ae9f40dd]ClassNaam::[/b:b4ae9f40dd]*pMoveCamera)(float speed); Zorg er ook voor dat je de functie uit je class als public declareert als je deze als externe op wilt roepen (of maak er een virtual functie van)[/b] Quote Link naar reactie
anoniem Geplaatst: 10 juni 2004 Auteur Delen Geplaatst: 10 juni 2004 Zou je iets precieser voor me kunnen zijn. Ik doe het nu als volgt (ergens uit een tutorial), maar het lukt nog niet: [code:1:41d9e838cc] stdafx.h: ========================================== class CCamera // CCamera klasse declareren { void MoveCamera(float speed); }; class CControl // CControl klasse declareren { void Keyboard(); }; void (CCamera::*pMoveCamera); // Pointer naar member functie declareren main.cpp: ========================================== #include stdafx.h main() { pMoveCamera = &CCamera::MoveCamera; // Pointer naar member functie maken // Ook pMoveCamera = &CCamera::MoveCamera(float speed) werkt niet. } control.cpp: ========================================== #include stdafx.h CControl::Keyboard() { pMoveCamera(0.5); // Functie uitvoeren } [/code:1:41d9e838cc] Krijg vervolgens op het moment dat ik de functie uitvoer de melding: term does not evaluate to a function Quote Link naar reactie
anoniem Geplaatst: 11 juni 2004 Auteur Delen Geplaatst: 11 juni 2004 void (CCamera::*pMoveCamera); // Pointer naar member functie declareren moet zijn: void (CCamera::*pMoveCamera)(float); // Pointer naar member functie declareren Je moet natuurlijk ook een object hebben waarbij je de functie gebruikt. Bijv: [code:1:b23a71086c] struct blaat { void functie(float speed){} }; int main() { // twee variabelen declareren (1 object)(2 pointer naar object) blaat one, *ptwo = &one; // *ptwo = pointer naar object one void (blaat::*pfunctie)(float) = &blaat::functie; // pointer naar member functie (one.*pfunctie)(); // oproep via one (mogelijkheid 1) (ptwo->*pfunctie)();} // oproep via pointer ptwo (mogelijkheid 2) [/code:1:b23a71086c] Quote Link naar reactie
anoniem Geplaatst: 11 juni 2004 Auteur Delen Geplaatst: 11 juni 2004 Dank voor het antwoord [DarthV]. De pointer wordt nu succesvol aangemaakt. Alleen werkt het niet zoals ik gedacht had en heb ik dus nog geen oplossing voor mijn probleem. Ik maak dus in main.cpp het object 'camera' aan m.b.v de classe CCamera (dus 'CCamera camera;') Deze is echter alleen in de code beschikbaar die in main.cpp staat. Kan ik een object, in dit geval dus 'camera', ook benaderen vanuit code die niet in main.cpp staat, maar in elk ander bestand uit mijn project? Quote Link naar reactie
anoniem Geplaatst: 12 juni 2004 Auteur Delen Geplaatst: 12 juni 2004 [quote:bf2167c52d]Kan ik een object, in dit geval dus 'camera', ook benaderen vanuit code die niet in main.cpp staat, maar in elk ander bestand uit mijn project?[/quote:bf2167c52d] Jawel hoor zolang je natuurlijk de class "included" hebt in het project. En ik neem aan dat je voor de functie's die je gebruikt ook het keyword public: hebt gezet zodat de member functies van buitenaf op te roepen zijn ? Verder zou ik je class niet maken in stdafx.h maar gewooon een eigen class file ervan maken. Suc6 in ieder geval Quote Link naar reactie
Aanbevolen berichten
Om een reactie te plaatsen, moet je eerst inloggen