Jump to content
  • Advertisement
Sign in to follow this  
f001error

typeid not working

This topic is 4326 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

G'day I need to check if my pointer my base class is actually a pointer to a particular child class: ie My Class hierarchary looks like this: ParentClass // base class ChildClass GrandChild Class // the class im checking for, also inherients from another class GreatGrandChild class my code looks like this
ParentClass* blah = *instanceIterator // blah comes from a list
if (typeid(blah) == typeid(Grandchild*)) // this should return true, since blah is a Grandchild class.
By my understanding typeid should work. I dont think it would make a difference but, GrandChild inherients from ChildClass and another class. Any ideas on what i'm doing wrong ?

Share this post


Link to post
Share on other sites
Advertisement
blah is a local pointer variable of type ParentClass*, so your code will always return false. Although it is of type ParentClass*, it happens to point at a polymorphic object of type GrandChildClass. This is the type you want to check (the type of the object, not the type of the pointer):

if (typeid(*blah) == typeid(GrandChildClass))

Share this post


Link to post
Share on other sites
Quote:
Original post by f001error
Any ideas on what i'm doing wrong ?

What you're doing wrong is (almost certainly) requiring a type-check to switch behaviour (type-switching, evil, brittle, error-prone) instead of using virtual functions.

Σnigma

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
blah is a local pointer variable of type ParentClass*, so your code will always return false. Although it is of type ParentClass*, it happens to point at a polymorphic object of type GrandChildClass. This is the type you want to check (the type of the object, not the type of the pointer):

if (typeid(*blah) == typeid(GrandChildClass))


Nope, still returning false :(


Quote:

What you're doing wrong is (almost certainly) requiring a type-check to switch behaviour (type-switching, evil, brittle, error-prone) instead of using virtual functions.

Σnigma


I can't use virtual functions for this. I've got a list of entites that are currently on screen, I'm iterating through that list, checking if the mouse is inside the entity. If it is, I then check to see if its a button subclass of entity. If it is a button I then fire off some code to handle the mouseover.

Share this post


Link to post
Share on other sites
Quote:
Original post by f001error
I can't use virtual functions for this. I've got a list of entites that are currently on screen, I'm iterating through that list, checking if the mouse is inside the entity. If it is, I then check to see if its a button subclass of entity. If it is a button I then fire off some code to handle the mouseover.


?


class BaseClass {
virtual OnMouseOver() = 0;
}
std::list<BaseClass*> objectsOnScreen;
for_each objectsOnScreen o {
o->OnMouseOver();
}


That said, I don't know why typeid isn't working, I've never used RTTI.

Share this post


Link to post
Share on other sites
If you really want to do this (which is a bad idea most of the time), then you can instead use dynamic_cast:


ScreenEntity * myScreenEntity = ...;
Button * b = dynamic_cast<Button *>(myScreenEntity);
if (b != 0) {
b->DoButtonStuff(where);
return;
}


However, if you have a list of screen entities, it makes more sense to build dispatching into the base class ScreenEntity. Being able to tell the engine whether you want a click or not is naturally part of being a screen entity.


class ScreenEntity {
public:
virtual bool ProcessMouseEvent(Point where) = 0;
};


so your code just becomes:


ScreenEntity * myScreenEntity = ...;
if (myScreenEntity->ProcessMouseEvent(where)) {
return;
}

Share this post


Link to post
Share on other sites
Are your types polymorphic to begin with? I don't think this could work unless they have at least one virtual function.

Share this post


Link to post
Share on other sites
An alternative to hplus0603's suggestion is to maintain two lists. One which contains all entities and another which contains only "mouseoverables", i.e.:
#include <algorithm>
#include <deque>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_deque.hpp>

class UserInterface;

class Entity
{

public:

virtual ~Entity(){}
virtual void render() = 0;

protected:

Entity(UserInterface & user_interface);

};

struct MouseCoordinates
{
unsigned short x;
unsigned short y;
};

class Mouseoverable
:
public virtual Entity
{

public:

virtual void on_mouse_over(MouseCoordinates coordinates) = 0;

protected:

Mouseoverable(UserInterface & user_interface);

};

class Label
:
public Entity
{

public:

static void create(UserInterface & user_interface);
virtual void render();

private:

Label(UserInterface & user_interface);

};

class Button
:
public Mouseoverable
{

public:

static void create(UserInterface & user_interface);
virtual void on_mouse_over(MouseCoordinates coordinates);
virtual void render();

private:

Button(UserInterface & user_interface);

};

class UserInterface
{

public:

void add(Entity & entity);
void add(Mouseoverable & mouseoverable);
void mouse_move(MouseCoordinates coordinates);
void render();

private:

boost::ptr_deque< Entity > entities_;
std::deque< Mouseoverable * > mouseoverables_;

};

Entity::Entity(UserInterface & user_interface)
{
user_interface.add(*this);
}

Mouseoverable::Mouseoverable(UserInterface & user_interface)
:
Entity(user_interface)
{
user_interface.add(*this);
}

void Label::create(UserInterface & user_interface)
{
new Label(user_interface);
}

void Label::render()
{
// render label;
std::cout << "rendering label\n";
}

Label::Label(UserInterface & user_interface)
:
Entity(user_interface)
{
}

void Button::create(UserInterface & user_interface)
{
new Button(user_interface);
}

void Button::on_mouse_over(MouseCoordinates /*coordinates*/)
{
// do stuff
std::cout << "mouse over button\n";
}

void Button::render()
{
// render button
std::cout << "rendering button\n";
}

Button::Button(UserInterface & user_interface)
:
Mouseoverable(user_interface)
{
}

void UserInterface::add(Entity & entity)
{
entities_.push_back(&entity);
}

void UserInterface::add(Mouseoverable & mouseoverable)
{
mouseoverables_.push_back(&mouseoverable);
}

void UserInterface::mouse_move(MouseCoordinates coordinates)
{
std::for_each(mouseoverables_.begin(), mouseoverables_.end(), boost::bind(&Mouseoverable::on_mouse_over, _1, coordinates));
}

void UserInterface::render()
{
std::for_each(entities_.begin(), entities_.end(), boost::bind(&Entity::render, _1));
}

int main()
{
UserInterface user_interface;
Label::create(user_interface);
Button::create(user_interface);
user_interface.render();
MouseCoordinates mouse_coordinates = {320, 200};
user_interface.mouse_move(mouse_coordinates);
}



This is just an example I threw together. There may be design issues I haven't noticed. If so I'm sure Zahlman or someone else will point them out.

EDIT: added virtual inheritance to avoid one potential design issue.
EDIT2: and virtual destructor (oops!)

Σnigma

[Edited by - Enigma on September 17, 2006 6:06:24 AM]

Share this post


Link to post
Share on other sites
To take it a step further, I don't see why you have two separate kinds of entities anyway. From an OO point of view there is little correlation between 'Entity' (which I assume is something that 'lives' in your world) and a mouseover event (which belongs to the UI). I would rather see it like this: some entities are represented by a screen image that can be clicked. So it might be better to give all entities an 'clickable image' member, which can be used or not. Then all entities will become obedient little commies again and your problem non-existant.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!