virtual functions and dynamic casting

C

Christopher Pisz

My problem is my derived class is getting called twice instead of the base
and then the derived. I thought this was the purpose for virtuals and
dynamic casting :/
I want my base class to have its method called and then the derived class
have its method called. What am I not understanding?

Int the following code, my Event Tester class is getting called twice for
keyboard events when I step through the debugger:
//------------------------------------------------------------------------------------------

class GFXApplication : public EventHandler

{

public:

GFXApplication();

virtual ~GFXApplication();

virtual void Create(HINSTANCE hInstance);

virtual int Run();

virtual int ProcessEvent(Event * event);

..

..

..

class EventTester : public GFXApplication

{

public:

EventTester();

~EventTester();

int ProcessEvent(Event * event);

..

..

..

//--------------------------------------------------------------------------------------

unsigned EventManager::postEvent(Event * event)

{

m_eventQueue.push(event);


return static_cast<unsigned>(m_eventQueue.size());

}

//--------------------------------------------------------------------------------------

unsigned EventManager::postImmediateEvent(Event * event)

{

EventHandlerVector::iterator it;

for(it = m_eventHandlerVectors[event->m_type].begin(); it !=
m_eventHandlerVectors[event->m_type].end(); it++)

{

(*it)->ProcessEvent(event);

}

delete event;

return 0;

}

//--------------------------------------------------------------------------------------

unsigned EventManager::RegisterHandler(EventHandler * handler, EVENT_TYPE
type)

{

m_eventHandlerVectors[type].push_back(handler);

return static_cast<unsigned>(m_eventHandlerVectors[type].size());

}

//--------------------------------------------------------------------------------------

unsigned EventManager::RemoveHandler(EventHandler * handler, EVENT_TYPE
type)

{

EventHandlerVector::iterator result =
std::find(m_eventHandlerVectors[type].begin(),
m_eventHandlerVectors[type].end(), handler);

if(result != m_eventHandlerVectors[type].end())

m_eventHandlerVectors[type].erase(result);

return static_cast<unsigned>(m_eventHandlerVectors[type].size());

}

//--------------------------------------------------------------------------------------

void EventManager::Update()

{

// Have every registered event handler process thier events

while(!m_eventQueue.empty())

{

Event * event = m_eventQueue.front();

m_eventQueue.pop();

EventHandlerVector::iterator it;

for(it = m_eventHandlerVectors[event->m_type].begin(); it !=
m_eventHandlerVectors[event->m_type].end(); it++)

{

(*it)->ProcessEvent(event);

}

delete event;

}

}

..

..

..

//-----------------------------------------------------------------------------

void GFXApplication::Create(HINSTANCE hInstance)

{

// Save the module handle

m_instance = hInstance;

// Register event handling

EventManager::GetInstance()->RegisterHandler(dynamic_cast<GFXApplication
*>(this), EVENT_WINDOWS);

EventManager::GetInstance()->RegisterHandler(dynamic_cast<GFXApplication
*>(this), EVENT_KEYBOARD);

..

..

..

//---------------------------------------------------------------------------

EventTester::EventTester()

:

GFXApplication()

{

EventManager::GetInstance()->RegisterHandler(this, EVENT_KEYBOARD);

EventManager::GetInstance()->RegisterHandler(this, EVENT_MOUSE);

..

..

..

//-------------------------------------------------------------------------------

int GFXApplication::processEvent(Event * event)

{

switch(event->m_type)

{




case EVENT_KEYBOARD:

{

// Update the keystates

m_keystates[ event->m_data.keyboardEventData.key ] =
event->m_data.keyboardEventData.pressed;

break;

}

default:

break;

} // End main switch

return 0;

}

..

..

..

int EventTester::processEvent(Event * event)

{

switch(event->m_type)

{

// These keyboard events are straight from the message loop and
unsatisfatory

// for controls that allow the key to be held down without accepting the
delay

// between the first keypress and the repeat. There is a minimum of a 250ms
delay

// For those types of controls, like flight steering for example, poll the

// keystate in the PreRender method.

case EVENT_KEYBOARD:

if(event->m_data.keyboardEventData.pressed)

{

switch(event->m_data.keyboardEventData.key)

{

default:

break;

}

}

break;

..

..

..
 
K

Karim

My problem is my derived class is getting called twice instead of the base
and then the derived. I thought this was the purpose for virtuals and
dynamic casting :/
I want my base class to have its method called and then the derived class
have its method called. What am I not understanding?

Int the following code, my Event Tester class is getting called twice for
keyboard events when I step through the debugger:
//------------------------------------------------------------------------------------------

class GFXApplication : public EventHandler

{

public:

GFXApplication();

virtual ~GFXApplication();

virtual void Create(HINSTANCE hInstance);

virtual int Run();

virtual int ProcessEvent(Event * event);

.

.

.

class EventTester : public GFXApplication

{

public:

EventTester();

~EventTester();

int ProcessEvent(Event * event);

.

.

.

//--------------------------------------------------------------------------------------

unsigned EventManager::postEvent(Event * event)

{

m_eventQueue.push(event);

return static_cast<unsigned>(m_eventQueue.size());

}

//--------------------------------------------------------------------------------------

unsigned EventManager::postImmediateEvent(Event * event)

{

EventHandlerVector::iterator it;

for(it = m_eventHandlerVectors[event->m_type].begin(); it !=
m_eventHandlerVectors[event->m_type].end(); it++)

{

(*it)->ProcessEvent(event);

}

delete event;

return 0;

}

//--------------------------------------------------------------------------------------

unsigned EventManager::RegisterHandler(EventHandler * handler, EVENT_TYPE
type)

{

m_eventHandlerVectors[type].push_back(handler);

return static_cast<unsigned>(m_eventHandlerVectors[type].size());

}

//--------------------------------------------------------------------------------------

unsigned EventManager::RemoveHandler(EventHandler * handler, EVENT_TYPE
type)

{

EventHandlerVector::iterator result =
std::find(m_eventHandlerVectors[type].begin(),
m_eventHandlerVectors[type].end(), handler);

if(result != m_eventHandlerVectors[type].end())

m_eventHandlerVectors[type].erase(result);

return static_cast<unsigned>(m_eventHandlerVectors[type].size());

}

//--------------------------------------------------------------------------------------

void EventManager::Update()

{

// Have every registered event handler process thier events

while(!m_eventQueue.empty())

{

Event * event = m_eventQueue.front();

m_eventQueue.pop();

EventHandlerVector::iterator it;

for(it = m_eventHandlerVectors[event->m_type].begin(); it !=
m_eventHandlerVectors[event->m_type].end(); it++)

{

(*it)->ProcessEvent(event);

}

delete event;

}
}

.

.

.

//-----------------------------------------------------------------------------

void GFXApplication::Create(HINSTANCE hInstance)

{

// Save the module handle

m_instance = hInstance;

// Register event handling

EventManager::GetInstance()->RegisterHandler(dynamic_cast<GFXApplication
*>(this), EVENT_WINDOWS);

EventManager::GetInstance()->RegisterHandler(dynamic_cast<GFXApplication
*>(this), EVENT_KEYBOARD);

.

.

.

//---------------------------------------------------------------------------

EventTester::EventTester()

:

GFXApplication()

{

EventManager::GetInstance()->RegisterHandler(this, EVENT_KEYBOARD);

EventManager::GetInstance()->RegisterHandler(this, EVENT_MOUSE);

.

.

.

//-------------------------------------------------------------------------------

int GFXApplication::processEvent(Event * event)

{

switch(event->m_type)

{

case EVENT_KEYBOARD:

{

// Update the keystates

m_keystates[ event->m_data.keyboardEventData.key ] =
event->m_data.keyboardEventData.pressed;

break;

}

default:

break;

} // End main switch

return 0;

}

.

.

.

int EventTester::processEvent(Event * event)

{

switch(event->m_type)

{

// These keyboard events are straight from the message loop and
unsatisfatory

// for controls that allow the key to be held down without accepting the
delay

// between the first keypress and the repeat. There is a minimum of a 250ms
delay

// For those types of controls, like flight steering for example, poll the

// keystate in the PreRender method.

case EVENT_KEYBOARD:

if(event->m_data.keyboardEventData.pressed)

{

switch(event->m_data.keyboardEventData.key)

{

default:

break;

}
}

break;

.

.

.


You need to add the keyword "virtual" on before all overriding funcs.
decalarations. The function of the instantiated class only will be
called, chaining will be done only in destructors as far as i know. If
you want to call the first one first, simply add this line t the
beginning of the derived class's function
GFXApplication::processEvent(event)
 
V

Victor Bazarov

Christopher said:
My problem is my derived class is getting called twice instead of the
base and then the derived. I thought this was the purpose for
virtuals and dynamic casting :/
I want my base class to have its method called and then the derived
class have its method called. What am I not understanding?

Int the following code, my Event Tester class is getting called twice
for keyboard events when I step through the debugger:
//------------------------------------------------------------------------------------------
[..badly formatted, incomplete, non-compilable, code removed..]

You couldn't have posted in worse shape, even if you tried, probably.

I couldn't make heads or tails of the code, I am sorry. Why do you
use 'dynamic_cast' to the same type from 'this'?

Anyway, if you think you're having a language problem (which I am not
sure you do, however), remove unnecessary code and make sure you have
read and follow the recommendations in FAQ 5.8. Most likely you have
some kind of logic problem, but with the code you posted it was not
possible to assertain without spending too much time trying to get it
back in shape.

V
 
C

Christopher Pisz

Victor Bazarov said:
Christopher said:
My problem is my derived class is getting called twice instead of the
base and then the derived. I thought this was the purpose for
virtuals and dynamic casting :/
I want my base class to have its method called and then the derived
class have its method called. What am I not understanding?

Int the following code, my Event Tester class is getting called twice
for keyboard events when I step through the debugger:
//------------------------------------------------------------------------------------------
[..badly formatted, incomplete, non-compilable, code removed..]

You couldn't have posted in worse shape, even if you tried, probably.

I couldn't make heads or tails of the code, I am sorry. Why do you
use 'dynamic_cast' to the same type from 'this'?

Anyway, if you think you're having a language problem (which I am not
sure you do, however), remove unnecessary code and make sure you have
read and follow the recommendations in FAQ 5.8. Most likely you have
some kind of logic problem, but with the code you posted it was not
possible to assertain without spending too much time trying to get it
back in shape.

V



All the pertinant code was there, I really don't think you want 900 lines in
a post. But if it makes it easier, here is a fictionous example:

class A
{
public:
A();
virtual ~A(){};
virtual int DoStuff();
};

class B : public A
{
public:
B();
virtual ~B(){};
int DoStuff();
};

class C
{
public:
C()
{
m_handler[0] = NULL;
m_handler[1] = NULL;
}

void Register(A * who)
{
if(!m_handler)
m_handler = who;
else
m_handler[2] = who;
}

void SomeFunction()
{
m_handler[0]->DoStuff();
m_handler[1]->DoStuff();
}
private:
A * m_handler[2];
};

C g_c;

A::A()
{
g_c.Register(this);
}

B:B()
{
g_c.Register(this);
}

int main()
{
B b;

g_c.SomeFunction();

return 0;
}




B::DoStuff() is getting called twice, even though B registered an instance
of itself as a B pointer and a pointer of itself as an A pointer. Since the
base class registered itself, why isn't the Base class's DoStuff() getting
called? I thought the purpose of virtual functions was that at run time, the
appropriate function would get called based upon what kind of pointer you
are working with. If it is a pointer to a B than B's function gets called
and if it is a pointer to an A than A's function should get called. So, why
isn't "this" in A being treated as a pointer to an object of the A type and
thusly having it's version of DoStuff() called?
 
V

Victor Bazarov

Christopher said:
[..]
All the pertinant code was there,

I don't doubt it. I just wasn't ready to do all the work formatting
it and making it compile just to find out that I am missing plenty
of something else. If you need our help, you have to work a little
bit for it.
I really don't think you want 900
lines in a post.

Of course not!
But if it makes it easier, here is a fictionous
example:

Doesn't compile/link either.
class A
{
public:
A();
virtual ~A(){};
virtual int DoStuff();
};

class B : public A
{
public:
B();
virtual ~B(){};
int DoStuff();
};

class C
{
public:
C()
{
m_handler[0] = NULL;
m_handler[1] = NULL;
}

void Register(A * who)
{
if(!m_handler)

This check is bogus. In an instance of 'C', 'm_handler' will
*never* be NULL.
m_handler = who;

No assignment to arrays is possible. Did you mean

m_handler[0] = who;

?
else
m_handler[2] = who;

I am guessing you meant

m_handler[1] = who;

because 'm_handler' array doesn't have the element with index '2'.
}

void SomeFunction()
{
m_handler[0]->DoStuff();
m_handler[1]->DoStuff();
}
private:
A * m_handler[2];
};

C g_c;

A::A()
{
g_c.Register(this);
}

B:B()
B::B()

{
g_c.Register(this);
}

int main()
{
B b;

g_c.SomeFunction();

return 0;
}




B::DoStuff() is getting called twice, even though B registered an
instance of itself as a B pointer and a pointer of itself as an A
pointer.

It doesn't matter. You register the same object twice, and calling
a virtual function in the base class will lead to the _real_ object's
type function (the final overrider) to be called.
Since the base class registered itself, why isn't the Base
class's DoStuff() getting called? I thought the purpose of virtual
functions was that at run time, the appropriate function would get
called based upon what kind of pointer you are working with.

Not "working with", but "as created".
If it is
a pointer to a B than B's function gets called and if it is a pointer
to an A than A's function should get called. So, why isn't "this" in
A being treated as a pointer to an object of the A type and thusly
having it's version of DoStuff() called?

<shrug> I am guessing you don't understand the meaning or purpose
of virtual functions, or polymorphism for that matter.

Polymorphism in its primitive way of resolving the behaviour (your
'DoStuff' function) to the type with which the object was originally
created, won't work for you. I think you need to describe [to us]
what you are trying to accomplish with your registering. It seems
that you need to (a) make two unrelated classes AA and BB and make
them both inherit from A, and then (b) make your B class *contain*
two objects of each class ('AA' and 'BB'), and when 'B' is created
have it register both contained instances:
----------------------------------------------------------------
#include <cstdlib>
#include <iostream>
class A
{
public:
virtual ~A() {}
virtual int DoStuff() = 0;
};

class AA : public A {
int DoStuff() {
std::cout << "A::DoStuff()\n";
return 111;
}
};

class BB : public A
{
public:
int DoStuff() {
std::cout << "B::DoStuff()\n";
return 222;
}
};

class B
{
AA aa;
BB bb;
public:
B();
};

class C
{
public:
C()
{
m_handler[0] = NULL;
m_handler[1] = NULL;
}

void Register(A * who)
{
if(!m_handler[0])
m_handler[0] = who;
else
m_handler[1] = who;
}

void SomeFunction()
{
m_handler[0]->DoStuff();
m_handler[1]->DoStuff();
}
private:
A * m_handler[2];
};

C g_c;

B::B()
{
g_c.Register(&aa);
g_c.Register(&bb);
}

int main()
{
B b;

g_c.SomeFunction();

return 0;
}
 
C

Christopher Pisz

Victor Bazarov said:
Christopher said:
[..]
All the pertinant code was there,

I don't doubt it. I just wasn't ready to do all the work formatting
it and making it compile just to find out that I am missing plenty
of something else. If you need our help, you have to work a little
bit for it.
I really don't think you want 900
lines in a post.

Of course not!
But if it makes it easier, here is a fictionous
example:

Doesn't compile/link either.
class A
{
public:
A();
virtual ~A(){};
virtual int DoStuff();
};

class B : public A
{
public:
B();
virtual ~B(){};
int DoStuff();
};

class C
{
public:
C()
{
m_handler[0] = NULL;
m_handler[1] = NULL;
}

void Register(A * who)
{
if(!m_handler)

This check is bogus. In an instance of 'C', 'm_handler' will
*never* be NULL.
m_handler = who;

No assignment to arrays is possible. Did you mean

m_handler[0] = who;

?
else
m_handler[2] = who;

I am guessing you meant

m_handler[1] = who;

because 'm_handler' array doesn't have the element with index '2'.
}

void SomeFunction()
{
m_handler[0]->DoStuff();
m_handler[1]->DoStuff();
}
private:
A * m_handler[2];
};

C g_c;

A::A()
{
g_c.Register(this);
}

B:B()
B::B()

{
g_c.Register(this);
}

int main()
{
B b;

g_c.SomeFunction();

return 0;
}




B::DoStuff() is getting called twice, even though B registered an
instance of itself as a B pointer and a pointer of itself as an A
pointer.

It doesn't matter. You register the same object twice, and calling
a virtual function in the base class will lead to the _real_ object's
type function (the final overrider) to be called.
Since the base class registered itself, why isn't the Base
class's DoStuff() getting called? I thought the purpose of virtual
functions was that at run time, the appropriate function would get
called based upon what kind of pointer you are working with.

Not "working with", but "as created".
If it is
a pointer to a B than B's function gets called and if it is a pointer
to an A than A's function should get called. So, why isn't "this" in
A being treated as a pointer to an object of the A type and thusly
having it's version of DoStuff() called?

<shrug> I am guessing you don't understand the meaning or purpose
of virtual functions, or polymorphism for that matter.

Polymorphism in its primitive way of resolving the behaviour (your
'DoStuff' function) to the type with which the object was originally
created, won't work for you. I think you need to describe [to us]
what you are trying to accomplish with your registering. It seems
that you need to (a) make two unrelated classes AA and BB and make
them both inherit from A, and then (b) make your B class *contain*
two objects of each class ('AA' and 'BB'), and when 'B' is created
have it register both contained instances:
----------------------------------------------------------------
#include <cstdlib>
#include <iostream>
class A
{
public:
virtual ~A() {}
virtual int DoStuff() = 0;
};

class AA : public A {
int DoStuff() {
std::cout << "A::DoStuff()\n";
return 111;
}
};

class BB : public A
{
public:
int DoStuff() {
std::cout << "B::DoStuff()\n";
return 222;
}
};

class B
{
AA aa;
BB bb;
public:
B();
};

class C
{
public:
C()
{
m_handler[0] = NULL;
m_handler[1] = NULL;
}

void Register(A * who)
{
if(!m_handler[0])
m_handler[0] = who;
else
m_handler[1] = who;
}

void SomeFunction()
{
m_handler[0]->DoStuff();
m_handler[1]->DoStuff();
}
private:
A * m_handler[2];
};

C g_c;

B::B()
{
g_c.Register(&aa);
g_c.Register(&bb);
}

int main()
{
B b;

g_c.SomeFunction();

return 0;
}

Ok, I think I get it. It doesn't matter what kind of pointer it is, it
matters what kind of object got created, if I understand you right. That
blows my whole architecture out the window :( I wanted to have an event
mechanism in my architecture that was capable of disbatching user defined
events to differant objects that register to recieve them. In this case, My
main application class is registered to receive keyboard events from the
operating system. The OS alerts me of keyboard input, An event manager grabs
that input and translates it into a more friendly event and disbatches it to
the main application to handle. My main application class, in this case
GFXApplication, is working as an "engine" or "framework" and is to take that
keyboard event and keep track of key states. The derived class, which is not
so general, but a specific application, in my first demo a space game, is to
also receive keyboard events, but for a differant purpose. The derived class
can grab the same events, that the GFXApplication did to fill the states,
and use keystrokes as Windows gives them...which involves a delay before
repeats when holding a key down...or if the key is used for some control
that requires repeats without delay, such as flight steering, it can poll
the table. So, GFXApplications uses it ProcessEvent function to fill the
table, and the derived class uses its Process event to process input one key
at a time.

It wouldn't be as simple as calling, GFXApplication::processEvent() in the
derived class' ProcessEvent() function, because that would mean there should
only be one registered handler instead of two. If only the final derived
class registers, than the table does not get filled. If both register, than
the event happens twice. I wanted to have any level of the inheritance to
register for whatever purpose is appropriate at that level, and have the
event dispatched only to that level.

I guess I am going to have to move the entire input mechanism away from the
appplication class. Perhaps into the event manager itself.
 
F

Frank Birbacher

Hi!

Christopher Pisz schrieb:
[snipped a lot of lines]

Pleas reduce the size of your posts by deleting lines you are not
responding to.
I guess I am going to have to move the entire input mechanism away from the
appplication class. Perhaps into the event manager itself.

As suggested by Victor you can move these functionalities into separate
classes and use them:

class KeyboardState : public EventHandler
{
private:
bool pressedKeys[105]; //or whatever state you need
protected:
virtual int processEvent(Event* event)
{
//update keyboard state
}
};

class GFXApplication
{
private:
KeyboardState keyboardTracker;
public:
GFXApplication
{
EventManager::GetInstance()->
RegisterHandler(
&keyboardTracker,
EVENT_KEYBOARD
);
}
};

and so on

I hope you get the idea.

HTH,
Frank
 
B

BobR

Christopher Pisz said:
I guess I am going to have to move the entire input mechanism away from the
appplication class. Perhaps into the event manager itself.

Maybe look into "Multiple dispatching Visitor pattern ( GoF ).

There is a (somewhat) simple example in "Thinking in C++" Vol. 2.
Chapter 10: Design Patterns, section 'Multiple dispatching'.

Get "Thinking in C++", 2nd ed. Volume 1&2 by Bruce Eckel
(available for free here. You can buy it in hardcopy too.):
http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top