Sign in to follow this  
bengaltgrs

Get inherited class object

Recommended Posts

Using the example below, how could I get the Character from the Object level?
class Object
{
public:
	Object(void);
	~Object(void);

	virtual Object* Get(void);
};

class Character : public Object
{
public:
	Character(void);
	~Character(void);
	
	Character* Get(void)
	{
		return this;
	}
}

//Use case
Character* someCharacter = new Character();
Object* newObject = someCharacter;
Character* newCharacter = newObject->Get();

Share this post


Link to post
Share on other sites
Your inheritance is wrong. Functions must have the same signature in order to override the one in the super class. Because the return types differ, the function declared in Character merely hides the one in Object, when calling on a character instance (static, not dynamic type). When the same instance is wrapped in a Object pointer or reference, the function calling an Object is returned. edit: Wrong, and irrelevant.

The solution is dynamic_cast:

class Object
{
public:
Object();
virtual ~Object();

virtual void example() { std::cout << "Generic Object\n"; }
};

class Character : public Object
{
public:
Character(void);
virtual ~Character(void);

virtual void example() { std::cout << "Character Object\n"; }

void special() { std::cout << "Special stuff objects can't do\n"; }
}

//Use case
Object *object = new Character();

object->example();

if( Character *character = dynamic_cast<Character*>(object) )
{
chatacter->special();
}





Note: use of dynamic cast is often indicative of a design flaw. Either you haven't modelled the base class properly, or the inheritance model doesn't make sense. It depends though, can you tell us why you need to do this, there may be a cleaner and more maintainable solution? After all, inheritance is all about not caring about the run time type of the object.

[Edited by - rip-off on February 20, 2008 4:35:07 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Your inheritance is wrong. Functions must have the same signature in order to override the one in the super class. Because the return types differ, the function declared in Character merely hides the one in Object, when calling on a character instance (static, not dynamic type). When the same instance is wrapped in a Object pointer or reference, the function calling an Object is returned.


It looks fine to me, C++ supports covariant return types. Or am I missing something obvious?

Share this post


Link to post
Share on other sites
The declarations of the classes are technically legal, but probably not what the OP had in mind, as he implicitly casts a Character* to a Object*, then hopes to have the Character version of Get be called.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Your inheritance is wrong. Functions must have the same signature in order to override the one in the super class. Because the return types differ, the function declared in Character merely hides the one in Object.

Er, no. The return type is not part of the function signature and therefore you cannot overload or hide based only on return type. Character::Get therefore is an override and is legal because the return type is covariant with the return type of the overridden function.

Σnigma

Share this post


Link to post
Share on other sites
I never knew that. I guess I assumed the entire signature had to match. Even still, it doesn't matter here because it is the static type that is important: the static type of the calling variable must be already be Character to assign the return value of Get() to a Character, right? (or have I messed up again [smile])

Share this post


Link to post
Share on other sites
The actual use for this is for a level editor. I have a vector of objects which includes lights, characters, etc. I also have a value for each type of object to keep track of which objects are selected; this is so I can directly access the selected object and call it's functions. There most likely is a cleaner way to do this, yes, but this is the first way that came to mind:



enum OBJECT_TYPES{LIGHT, CHARACTER}:
class Object
{
public:
Object(void);
~Object(void);

virtual Object* Get(void);
int Type;
float3 Position;
};

class Character : public Object
{
public:
Character(void);
~Character(void);

float yRotation;
int Health;
//etc....

Character* Get(void)
{
return this;
}
};

std::vector<Object*> Objects; //Holds all characters, lights, etc..
Character* SelectedCharacter;

Character* GetClosestCharacter()
{
Character* tempCharacter = NULL;
for(int i = 0; i < Objects.size(); i++)
{
if(Objects[i]->Type == CHARACTER)
{
//if closest character
tempCharacter = Objects[i]->Get();
}
}

return tempCharacter;
}





The reason I did it this way was because I wanted to keep a selected member of each type of object, and if I use an Object to hold them then I can't access the Character/Light specific variables (Character->Health).

[Edited by - bengaltgrs on February 20, 2008 5:04:03 PM]

Share this post


Link to post
Share on other sites

Character* GetClosestCharacter() {
for(int i = 0; i < Objects.size(); i++) {
Character * temp = dynamic_cast<Character *>(Objects[i]);
if (temp) return temp;
}
}

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane

Character* GetClosestCharacter() {
for(int i = 0; i < Objects.size(); i++) {
Character * temp = dynamic_cast<Character *>(Objects[i]);
if (temp) return temp;
}
return NULL; // there are no characters
}


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