Get inherited class object

Started by
7 comments, last by Zahlman 16 years, 2 months ago
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();

Advertisement
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 caseObject *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]
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?
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.
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
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])
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->Type == CHARACTER)                {                         //if closest character                         tempCharacter = Objects->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]
Character* GetClosestCharacter() {  for(int i = 0; i < Objects.size(); i++) {    Character * temp = dynamic_cast<Character *>(Objects);    if (temp) return temp;  }}
Quote:Original post by SiCrane
Character* GetClosestCharacter() {  for(int i = 0; i < Objects.size(); i++) {    Character * temp = dynamic_cast<Character *>(Objects);    if (temp) return temp;  }  return NULL; // there are no characters}


This topic is closed to new replies.

Advertisement