By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,661 Members | 781 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,661 IT Pros & Developers. It's quick & easy.

virtual functions and dynamic casting

P: n/a
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;

..

..

..



Aug 10 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
On Aug 10, 1:28 pm, "Christopher Pisz" <some...@somewhere.netwrote:
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)

Aug 10 '07 #2

P: n/a
Christopher Pisz wrote:
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 10 '07 #3

P: n/a
>"Victor Bazarov" <v.********@comAcast.netwrote in message
>news:f9**********@news.datemas.de...
Christopher Pisz wrote:
>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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


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?
Aug 10 '07 #4

P: n/a
Christopher Pisz wrote:
[..]
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;
}
----------------------------------------------------------------
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 10 '07 #5

P: n/a

"Victor Bazarov" <v.********@comAcast.netwrote in message
news:f9**********@news.datemas.de...
Christopher Pisz wrote:
>[..]
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;
}
----------------------------------------------------------------
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
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.


Aug 10 '07 #6

P: n/a
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
Aug 10 '07 #7

P: n/a

Christopher Pisz <so*****@somewhere.netwrote in message...
>
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/...ngInCPP2e.html

--
Bob R
POVrookie
Aug 10 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.