Derived class being treated as a base class

Started by
7 comments, last by starstriker1 18 years, 5 months ago
This is my problem:

class base
{
}

class derived
{
}

class other
{
virtual void handle(base *target);
virtual void handle(derived *target);
}
My problem is that when I pass a derived class to the handle function, it calls the "base *target" function as opposed to the "derived *target" one. Is there a way around this?
Advertisement
I've just had a similiar thing with MSVC++ v6. If that is what you are using then I'm not surprised.
In my case it was like this:
class base {	friend bool operator < (const base& a, const base& b);};class derived: public base {	friend bool operator < (const derived& a, const derived& b);};
I then called it as follows:
derived foo = 3;if (foo < (derived)4){	// Do something}
But it kept calling base operator < instead!

I had to change the derived operator to:
	bool operator < (const derived& b) const;
Which worked around the problem. So perhaps you can think along those lines.
Or better yet, download the free VS2003 compiler!

I've omitted a lot of code to keep the post short. If you feel that I need to post missing bits, please ask.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Could you post the source code where you're calling the method AND the actual class definitions for base and derived? You needn't include the whole definition for the classes, just the "class derived : public base" part and the definition for the methods you're having troubles with.
What exactly are you passing to the function? The below works as expected for VC++ 2003:
#include <iostream>#include <string>class base {   std::string s_;public:   base( std::string s ):s_(s) {}   void name() { std::cout << s_ << std::endl; }};class derived : public base {public:   derived( std::string s ):base(s) {}};void foobar( base * b ) { std::cout << "foobar( base * ): "; b->name(); }void foobar( derived * d ) { std::cout << "foobar( derived * ): "; d->name(); }int main() {   base B( "base" );   derived D( "derived" );   foobar( &B );   foobar( &D );   base * BpB = new base( "base pointer to base" );   base * BpD = new derived( "base pointer to derived" );   derived * DpD = new derived( "derived pointer to derived" );   foobar( BpB );   foobar( BpD );   foobar( DpD );   delete BpB;   delete BpD;   delete DpD;   return 0;}

EDIT: Also, could you explain what these functions do? There may be other options than overloading for base/derived pointers.
:stylin: "Make games, not war.""...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
Are you sure it is actually type pointer to derived rather than type pointer to base that happens to be pointing to an instance of derived? The compiler is going to select the function based upon the type of the pointer without regard to what it is actually pointing at. If it is a pointer to base then handle(base *target) is the correct function to call. You really should examine why you have two versions of the same function with one operating on the base and another operating on derived. There should be virtual functions in base that allow code one handle(base *target) that operates on either base or derived.
Keys to success: Ability, ambition and opportunity.
I am using MSVC++ 6, so that could indeed be part of the problem.

I can't give you the code right now, I'll post that later. However, I can tell you what I'm trying to do:

I have a system where every object, players, projectiles, pickups, etc, are all "gameObjects". More specific types such as "playerObject", "physBoxObject", or the ones I'm having problems with, "destroyableObject" and "projectileObject", are derived from this. Every frame, each object is updated by itself, and then again against all other objects.

destroyableObject is derived from physBoxObject, making it basically the same except that it has health, and functions for handling health (changeHealth, setHealth, getHealth, etc.) projectileObject is also inherited from physBoxObject, though the only differences are how individual functions are implemented. I want the projectileObject object to object handling function to be able to recognize when a destroyableObject (or anything derived from it) is passed to it so it can call these health handling functions.

I could just add the health handling functions to gameObject and be done with it, but that would be far more information than the gameObject class should have to deal with.
What about a message structure. Say projectible passes a message saying damage health. If an object with health receives that message then it processes it appropriately, but if an object without health receives it the message is ignored. Alternatively you could use query functions such as "HasHealth". If the query says it has health then you cast the pointer up to the base class for all objects that have health.

With the message structure all a particular class needs to know is the messages it generates. With the query structure the it has to know a good deal about the class hierarchy and the individual classes.
Keys to success: Ability, ambition and opportunity.
C++ only has single dispatch, which means that overload resolution in this case will be done against the compile-time type of the variable, not the runtime type. The method called only depends on the runtime type of the "this" object, not any parameters.

A system in which method dispatch relies on the runtime type of all parameters, including the "this" object, is called multiple dispatch or multimethods. CLOS is notable for supporting this, but I can't think of any languages in actual use (smuglispweenies: Don't bother. Just don't.) that have language support for multimethods.
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
Thanks for the help, guys. Its working now, and quite well!

I ended up going with the message system LilBudyWizer suggested. I'm worried that it might cause trouble down the road, though I have no clue why... chalk that up to paranoia, I guess!

This topic is closed to new replies.

Advertisement