Sign in to follow this  
starstriker1

Derived class being treated as a base class

Recommended Posts

starstriker1    245
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?

Share this post


Link to post
Share on other sites
iMalc    2466
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.

Share this post


Link to post
Share on other sites
smr    2468
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.

Share this post


Link to post
Share on other sites
stylin    758
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.

Share this post


Link to post
Share on other sites
LilBudyWizer    491
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.

Share this post


Link to post
Share on other sites
starstriker1    245
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.

Share this post


Link to post
Share on other sites
LilBudyWizer    491
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.

Share this post


Link to post
Share on other sites
Arild Fines    968
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.

Share this post


Link to post
Share on other sites
starstriker1    245
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!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this