3

I've been looking at some related threads but still don't find anything that answers the following question.

Let's say I have a hierarchy of classes (e.g. Widgets, HTML element) that form a tree structure. When I walk through the tree or look for a concrete element based on its ID I get a pointer to the base class (the tree algorithms only know about the base class).

Then, based on the type (the base class has a field that identifies the type) I perform a dynamic_cast in order to get a pointer to the concrete type. I've been thinking about ways to avoid this. The only thing that comes to my mind is the visitor pattern. But don't like very much this pattern.

Are there other ways/patterns to search/iterate nodes and get a pointer to the concrete class without using RTTI nor the visitor pattern?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
user1192525
  • 657
  • 4
  • 20
  • What are you going to do with this pointer? If you're only calling methods you might get away with virtual methods. – Some programmer dude Mar 14 '13 at 09:43
  • 6
    If your polymorphic hierarchy is well designed, you can get away with virtual calls and don't resort to the more expensive dynamic cast. – dtech Mar 14 '13 at 09:43
  • 1
    Why don't you like the pattern? – StoryTeller - Unslander Monica Mar 14 '13 at 09:45
  • Why not just use a static_cast instead of a dynamic_cast? – selbie Mar 14 '13 at 09:45
  • @selbie: It's not a question of performance; he doesn't want to do the type conversion. – Nicol Bolas Mar 14 '13 at 09:46
  • @selbie A `static_cast` cannot go down the heirarchy. – Alex Chamberlain Mar 14 '13 at 09:48
  • @ddriver: The problem is that I need to downcast as the concrete classes provide a specific set of methods. Let's say I have two widgets: TextWidget and ImageWidget. Both can have a common method called paint(). But TextWidget can have a method called clearText() and ImageWidget can have another method called rotateImage(). In order to invoke this specific methods I need to downcast the pointer. – user1192525 Mar 14 '13 at 09:50
  • @AlexChamberlain - BS. It absolutely can be used to downcast from a base class to a derived class safely - provided you are sure that it is the type you are casting to. – selbie Mar 14 '13 at 09:50
  • 1
    @user1192525 - I get the idea but what you speak of sounds like a terribly bad design intent. Entire frameworks exist to tackle that kind of problem, you can look at Qt's properties which can be listed, changed or even added during runtime. There is a meta object compiler that generates all the necessary boiler plate code, on top of the meta object system. And all this is type agnostic, all you need is to derive from QObject. – dtech Mar 14 '13 at 09:54
  • @selbie - then if I know for sure that the type is right, I could use static_cast, couldn't I? – user1192525 Mar 14 '13 at 09:55
  • 1
    @user1192525 - Absolutely safe to use static_cast for downcasting if you **know** the object is really of that type. – selbie Mar 14 '13 at 09:57
  • The real question is why do you have to case to concrete type, and not use virtual methods. However, if it is really what you want, we are talking about double dispatch. As you mention avoiding RTTI and visitior pattern, I guess that you are aware of this question: http://stackoverflow.com/questions/12582040/understanding-double-dispatch-c/12582114#12582114 – Zdeslav Vojkovic Mar 14 '13 at 09:59
  • @ddriver Thanks. I'm looking at the meta object system in Qt. Looks really interesting. – user1192525 Mar 14 '13 at 10:01
  • @user1192525: Wait: if you're willing to use a cast... what's *wrong* with `dynamic_cast`? static or dynamic, it's still a conversion operation. So why is `dynamic_cast` bad but `static_cast` is good? – Nicol Bolas Mar 14 '13 at 10:08

2 Answers2

0

Your approach doesn't sound like a good idea. Mostly because you have to do all the considerations before the runtime.

What you want to do is basically have the specific properties of a object listed and accessible. With dynamic casting this is possible but hardly elegant - since you have to write a trainload of switches and hardcode each and every possibility in advance so you can use it at runtime.

The solution I'd recommend as usual is the Qt framework. You can list the properties for each object at runtime, access a specific property by its name string or index and even attach properties during the runtime that don't exist in the code. And all this is type agnostic, you don't need to know an object's type to know its properties, and lastly - Qt offers a significantly faster qobject_cast for QObject derived classes instead of dynamic_cast.

The meta system allows you to know the class name, the base class name, methods, enums, constructors and pretty much everything, so besides properties, it is a good source for accessing all the functionality, available to an instance.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • 1
    "*since you have to write a trainload of switches and hardcode each and every possibility in advance so you can use it at runtime.*" That would be the visitor pattern. He *knows* what the type is statically. So the dynamic cast would not involve any switches and such. – Nicol Bolas Mar 14 '13 at 10:09
  • @NicolBolas - He wants to have access to the full set of properties and methods of items in a polymorphic tree. I don't think this is possible without hardcoding every single option in advance. The `dynamic_cast` will confirm if a pointer is of a given class, but that's about it, he is still limited to what is hardcoded. He will still need to switch based on what the type is and switch between the individual functionality, available to the particular instance. – dtech Mar 14 '13 at 10:17
  • He seems to think it is, since he said that `static_cast` would work for him. So, at the time of use, he clearly knows exactly what type it is statically. – Nicol Bolas Mar 14 '13 at 10:18
  • @NicolBolas - I think you are missing the bigger issue here - knowing what the type is - that is only the tip of the iceberg. If he wants to invoke properties and methods at runtime, knowing the type is only a tiny step, he will still need to index and hard-code each and every scenario. The Qt meta system can do all that work for him, work that grows with the number of classes in the hierarchy and its depth. – dtech Mar 14 '13 at 10:27
0

It really depends on the implementation of the visitor pattern. Using dynamic_cast<> is one way, another might be to use a handcrafted RTTI by defining a virtual GetType() function which can be implemented in all the subclasses. Depending on the result of that function you can do different things.

Martin Komischke
  • 1,440
  • 1
  • 13
  • 24