When casting a class over a base class, anyway to tell if it is the right class?

Started by
12 comments, last by LordShade 18 years, 4 months ago
Quote:Original post by Glak
using typeid stuff is pretty much the same as casting, and indicates a problem. You should not need to get derived class information from something assigned to a base pointer. If you want to access Sound or whatever just make it global, either a global variable, global namespace, or global singleton. Some sort of global.


Eh... So you're saying you should use globals instead of casting?
Advertisement
Quote:Original post by dotproduct
Quote:Original post by Glak
using typeid stuff is pretty much the same as casting, and indicates a problem. You should not need to get derived class information from something assigned to a base pointer. If you want to access Sound or whatever just make it global, either a global variable, global namespace, or global singleton. Some sort of global.


Eh... So you're saying you should use globals instead of casting?


Sounds like bad advice to me. Partially, anyways.

typeid/dynamic_cast can be the smell of a design problem - that of too coarsely grained dat. You've got something which you don't know the type of, and by your solution's nature, it either should (e.g. change from "Base * b" to "Derived1 * d" - or mantain seperate containers of input and draw, instead of 1 of pointers all to base) or shouldn't (e.g. from "if ( derived1 ) b->do_something_derived1() else if ( derived2 ) ..." to "b->do_something()" which is a virtual which calls do_something_derived1/derived2/etc - or throws if it dosn't implement it).

That said, the solution is sometimes more complex than simply mantaining somewhat brittle code as illustrated above.

Just 2¢
Quote:using typeid stuff is pretty much the same as casting, and indicates a problem.


Note that you don't have to use typeid() in the implementation at all -- I just used it because it's an easy source of strings to use as interface identifiers. You could use names of football teams, or integers, if you want -- as long as you get a unique identifier per interface you may wish to query for.

A second note is that the use I'm making of typeid() is _not_ analogous to dynamic_cast<>, because it is resolved statically at compile time -- it'll work even if you turn off RTTI. Additionally, getInterface() lets you decide what specific classes to let others find pointers to, whereas dynamic_cast<> doesn't let you totally decide -- any public base of a public base will be accessible. Further, dynamic_cast<> doesn't support delegation, whereas getInterface() does. Last, dynamic_cast<> is very, very slow -- the strcmp() implementation of getInterface() I showed is much faster, and a version that uses interned strings or interface registries would be faster still.

A third note is that you CAN make a public accessor for any interface you may wish to get on any interface you may wish to get it from. However, that quickly becomes way too wide, and the getInterface() solution is actually more maintainable and easier to work with. Typical examples come when sorting out entities inside notifications -- i e, entity A collided with entity B, and wants to know whether entity B supports some special kind of resolution. You should NOT make it a rule that every entity needs to support the special resolution rules that entity A wants, nor even an accessor for those rules, or adding/improving your entity behavior system becomes ridiculously unweildy.

In fact, getInterface() allows you to de-couple your logical design from your physical design, which is a major benefit in many game programming situations. I you're going to say it's a bad design tool, then you're going to have to put a LOT more weight behind that statement, with specific examples of what better solution you have to the same problems. ("use a global" isn't, and "make Entity support abstract accessors for anything you might ever want" also isn't)
enum Bool { True, False, FileNotFound };
If you're going to go the way of the Type ID, why not take the plunge and go full-COM based objects? It has support for singletons and interfaces and with ATL is fairly easy to implement. Sure if you don't have any exposure to implementing COM objects, you've got some reading to do. Really though, COM is a great tool that is underutilized.

Again, if you're base class is asking the type of it's parent, you've got a 'cludge' and need to examine your design.

This topic is closed to new replies.

Advertisement