From: Dan P. <ba...@al...> - 2005-12-04 16:59:43
|
On Dec 4, 2005, at 8:21 AM, Sam Steele wrote: > Right now I'm keeping my own std::list<Entity *> of Entity pointers > so I don't lose them when they turn into Drawables in the list, but > I'm guessing RTTI would let me enumerate genmenu's m_scene to find > Entity-derived objects, and cast them from a Drawable pointer to an > Entity pointer to use the Entity-specific functions? Yes. You can take any pointer and try to upcast it to any other pointer, and if it's possible it'll give you the new pointer; otherwise it'll return NULL. If you do the same with an object or a reference, it'll throw an exception if it fails. One thing to be clear about, dynamic_cast is most useful for upcasting or cross-casting (which I think is what you want to do here). For example: A -> B -> C X -> Y / What my bad ASCII art there is saying is that B derives from A, Y derives from X, and C derives from B and Y. In this case, you ought to be able to cast a C to any of those things without any RTTI voodoo. You can also take an A* which is actually a C, and up-cast it to a C; RTTI lets you do this safely, if you don't know the A is a C already. Similarly if you have an X* which is actually a C, you can use RTTI to upcast to C, and I think you might be able to cross-cast to A or B (maybe with an intermediate C* cast), but again that's not too safe without using RTTI to check. > create_object("Paddle") returns an Entity* which is pointing to a > Paddle*. If I then call ent->loadFromFile(), then > Entity::loadFromFile() gets called, but not Paddle::loadFromFile > (). I think that's what the virtual keyword is for? Anyway, for > now I just have a second giant if/else called load_object() that > calls loadFromFile before the object gets cast to an Entity*. If I'm understanding correctly, it sounds like one way or another the compiler isn't seeing the virtual applying to what you're applying it to. That's the behavior you'd get if you had some method in both classes without 'virtual'. Another way this can happen is if you try to use it from the constructor. Calling virtuals from the constructor is a bad idea (ditto with the destructor). If you think about it for a minute you can see why. :) They made the language patch up the vtable at each step of construction/destruction to make this not as bad as it could be, but IMO they should've just made it illegal... Also the base class must be called explicitly from the derived method. This lets you wholly override functionality from a base class and also have better control over when the base class method gets called (before or after, etc). Unfortunately there's no smart way in C ++ to address the base class. So somewhere in your Paddle::loadFromFile() you need to have something like "Entity::loadFromFile()". > Now, m_light gets assigned a pointer in a linked list of where > lights are located (to make finding them as fast as possible for > vertex lighting). Anyway, it gets a value inside of Light();, but > as soon as it returns from that call, it goes back to being NULL > again before loadFromFile gets called. Is there another way I'm > supposed to call the default constructor from another constructor? AFAIK you can't call another constructor on the same object directly (someone correct me here if I'm wrong, because I'm a little fuzzy on this point). The standard idiom is this: class Foo { public: Foo(); Foo(int a); Foo(int a, int b); private: void init(int a, int b); }; Foo::Foo() { init(defa, defb); } Foo::Foo(int a) { init(a, defb); } Foo::Foo(int a, int b) { init(a, b); } void Foo::init(int a, int b) { // Real constructor guts } |