🔒 Locked
Function pointers in classes
Advertisement
Original Post
Okay, I''m sure this question has been asked a billion times, but I just can''t figure this out. Say I have some class like
class SomeClass
{
public:
void (* CurrentFunction)(void);
void Init(void);
void Blah(void);
private:
int Data;
};
SomeClass Test;
And then if you try to say something like
CurrentFunction = Init;
But then you get some conversion error, so you declare Init and Blah as static:
static void Init(void);
static void Blah(void);
and then this allows you to set CurrentFunction equal to one of these but then static function can''t access any member data of the class. So say then in Init() you want to set Data = 0:
void Init(void)
{
Data = 0;
}
This gives an error because static functions can''t access member data, nor do they have a this pointer. So then how do you do you have a class when a function pointer in it point to another function in the class so that the function its pointing to can access data in the class? Is this just impossible? I refuse to believe it, someone please help...
Pointer to function :
void (*CurrentFunction)(void);
CurrentFunction = SomeFunction;
CurrentFunction();
Pointer to nonstatic member function:
void (SomeClass::*CurrentFunction)(void);
CurrentFunction = &SomeClass::SomeFunction;
SomeClass object;
object.*CurrentFunction();
SomeClass* ptr = &object
ptr->*CurrentFunction();
It is impossible to use one in place of the other.
( e.g. Win32 API expects function pointers as callbacks, not member function pointers. )
Borland C++ and g++ let you cast back a bound PMF to a function pointer, but it is not standard behaviour.
Consider using function objects called by templated functions, where the syntax, not the type, matters. e.g. boost::function, boost::bind, boost::mem_fn, boost::signal. Seee boost link in sig.
Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
void (*CurrentFunction)(void);
CurrentFunction = SomeFunction;
CurrentFunction();
Pointer to nonstatic member function:
void (SomeClass::*CurrentFunction)(void);
CurrentFunction = &SomeClass::SomeFunction;
SomeClass object;
object.*CurrentFunction();
SomeClass* ptr = &object
ptr->*CurrentFunction();
It is impossible to use one in place of the other.
( e.g. Win32 API expects function pointers as callbacks, not member function pointers. )
Borland C++ and g++ let you cast back a bound PMF to a function pointer, but it is not standard behaviour.
Consider using function objects called by templated functions, where the syntax, not the type, matters. e.g. boost::function, boost::bind, boost::mem_fn, boost::signal. Seee boost link in sig.
Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
Okay, apparently I'm retarded because I just cannot get this to work. If I do the (Test.*CurrentFunction)() I get some error:
error C2065: 'CurrentFunction' : undeclared identifier
C:\Program Files\Microsoft Visual Studio\MyProjects\theorytest\main.cpp(160) : error C2297: '->*' : illegal, right operand has type 'int'
This comes despite the fact that Test CLEARLY has CurrentFunction in it. If I try just Test.*CurrentFunction I get the same two errors. I just don't get it... I can post some actual code if you want...
There's alot of extra crap in there but maybe someone can tell me what's going on that I get these errors. I don't know if I mentioned this, but I'm using VC++ 6 and Windows XP (not like I think the OS would matter but whatever...)
[Edit: please use source tags when posting tons of code. -Yann]
[edited by - Yann L on October 31, 2002 12:44:10 PM]
error C2065: 'CurrentFunction' : undeclared identifier
C:\Program Files\Microsoft Visual Studio\MyProjects\theorytest\main.cpp(160) : error C2297: '->*' : illegal, right operand has type 'int'
This comes despite the fact that Test CLEARLY has CurrentFunction in it. If I try just Test.*CurrentFunction I get the same two errors. I just don't get it... I can post some actual code if you want...
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <conio.h>
#include "gamedefs.h"
#include "script.h"
typedef enum {SPHERE, CUBE, CYLINDER} TRIGGERBOUNDTYPE;
typedef enum {INIT, TITLE, SCRIPT, MAINGAME, ENDGAME} GAMESTATE;
class CTrigger
{
public:
void operator = (const CTrigger& Trig)
{
m_BoundType = Trig.m_BoundType;
m_Script = Trig.m_Script;
m_xLocation = Trig.m_xLocation;
m_yLocation = Trig.m_yLocation;
m_zLocation = Trig.m_zLocation;
m_Triggered = Trig.m_Triggered;
}
CTrigger(const CTrigger& Trig) { *this = Trig; }
CTrigger();
CTrigger(float x, float y, float z, TRIGGERBOUNDTYPE BoundType, CScript Script);
CheckForTrigger(void);
private:
TRIGGERBOUNDTYPE m_BoundType;
CScript m_Script;
float m_xLocation;
float m_yLocation;
float m_zLocation;
bool m_Triggered;
};
CTrigger::CTrigger()
{
m_Triggered = false;
}
CTrigger::CTrigger(float x, float y, float z, TRIGGERBOUNDTYPE BoundType, CScript Script)
{
m_BoundType = BoundType;
m_Script = Script;
m_xLocation = x;
m_yLocation = y;
m_zLocation = z;
m_Triggered = false;
}
class CEngine
{
public:
CEngine();
~CEngine();
void (CEngine::*CurrentFunction)(void);
void Run(void) { (this->*CurrentFunction)(); }
void SetState(GAMESTATE NewState);
// Various states the game can be running in
void Test(void);
void EndGame(void);
void Init(void);
void MainGame(void);
void ScriptRunning(void);
void Title(void);
private:
CScript *m_Script;
GAMESTATE m_State;
};
void CEngine::Test(void)
{
cout << "Test called so apparently there's hope after all..." << endl;
}
CEngine::CEngine()
{
m_State = INIT;
CurrentFunction = &CEngine::Init;
}
CEngine::~CEngine()
{
}
void CEngine::SetState(GAMESTATE NewState)
{
switch(NewState)
{
case INIT:
{
m_State = INIT;
CurrentFunction = &CEngine::Init;
} break;
case TITLE:
{
m_State = TITLE;
CurrentFunction = &CEngine::Title;
} break;
case SCRIPT:
{
m_State = SCRIPT;
CurrentFunction = &CEngine::ScriptRunning;
} break;
case MAINGAME:
{
m_State = MAINGAME;
CurrentFunction = &CEngine::MainGame;
} break;
case ENDGAME:
{
m_State = ENDGAME;
CurrentFunction = &CEngine::EndGame;
} break;
}
}
// Functions for the various states of the engine:
void CEngine::EndGame(void)
{
}
void CEngine::Init(void)
{
// Initialize everything that should be initialize ie graphics and such
// [...]
// Move on to the title
SetState(TITLE);
}
void CEngine::MainGame(void)
{
cout << "Alright here's the main game, awesome, eh?" << endl;
getch();
SetState(ENDGAME);
}
void CEngine::ScriptRunning(void)
{
}
void CEngine::Title(void)
{
cout << endl << "Welcome to the earliest version of Blue Snood 3d imaginable" << endl;
getch();
SetState(MAINGAME);
}
void main(void)
{
CEngine Engine;
CScript GameScript;
ifstream infile;
string filename;
Engine.CurrentFunction = &(CEngine::Test);
(Engine.*CurrentFunction)();
cout << "Enter the script file you want to open: ";
cin >> filename;
infile.open(filename.c_str());
if(infile.fail())
cout << "Unable to open script " << filename << "!" << endl;
infile >> GameScript;
infile.close();
}
void CharacterDialog(string text)
{
cout << "Dialog called" << endl;
cout << text << endl;
}
void Delay(float num)
{
cout << "Delay called with an argument of " << num << "!" << endl;
}
void LaunchGoblin(float x, float y, float z)
{
cout << "Goblin launched at (" << x << ", " << y << ", " << z << ")!" << endl;
}
There's alot of extra crap in there but maybe someone can tell me what's going on that I get these errors. I don't know if I mentioned this, but I'm using VC++ 6 and Windows XP (not like I think the OS would matter but whatever...)
[Edit: please use source tags when posting tons of code. -Yann]
[edited by - Yann L on October 31, 2002 12:44:10 PM]
Given that CurrentFunction is a member variable of Test and not a freestanding variable, I suppose that Test.*(Test.CurrentFunction)() would work better.
Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
Whoops, actually I typed in your suggestion wrong, but I still get one error:
C:\Program Files\Microsoft Visual Studio\MyProjects\theorytest\main.cpp(160) : error C2064: term does not evaluate to a function
Here''s the line where I try to call the function pointer:
C:\Program Files\Microsoft Visual Studio\MyProjects\theorytest\main.cpp(160) : error C2064: term does not evaluate to a function
Here''s the line where I try to call the function pointer:
Engine.*(Engine.CurrentFunction)();
[\CODE]
Regardless of how I assign the function to the function pointer, I still get the same errors when I try to execute the function pointer. I seriously didn''t think this would be that hard, is there just an error in my code that I missing? Didn''t I do everything just like I should?
I have been able to COMPILE and RUN your code.
I have only needed:
#include <fstream>
#include <string>
#include <conio.h>
#include <iostream>
using namespace std;
CScript { };
and a main like this:
void main(void)
{
CEngine Engine;
Engine.CurrentFunction = &(CEngine::Test);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(INIT);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(TITLE);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(SCRIPT);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(MAINGAME);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(ENDGAME);
(Engine.*Engine.CurrentFunction)();
getch();
}
I have only needed:
#include <fstream>
#include <string>
#include <conio.h>
#include <iostream>
using namespace std;
CScript { };
and a main like this:
void main(void)
{
CEngine Engine;
Engine.CurrentFunction = &(CEngine::Test);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(INIT);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(TITLE);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(SCRIPT);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(MAINGAME);
(Engine.*Engine.CurrentFunction)();
Engine.SetState(ENDGAME);
(Engine.*Engine.CurrentFunction)();
getch();
}
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement