Reputation: 6352
I need to find the type of object pointed by pointer. Code is as below.
//pWindow is pointer to either base Window object or derived Window objects like //Window_Derived.
const char* windowName = typeid(*pWindow).name();
if(strcmp(windowName, typeid(Window).name()) == 0)
{
// ...
}
else if(strcmp(windowName, typeid(Window_Derived).name()) == 0)
{
// ...
}
As i can't use switch statement for comparing string, i am forced to use if else chain. But as the number of window types i have is high, this if else chain is becoming too lengthy. Can we check the window type using switch or an easier method ?
EDIT: Am working in a logger module. I thought, logger should not call derived class virtual function for logging purpose. It should do on its own. So i dropped virtual function approach.
Upvotes: 1
Views: 3446
Reputation: 30819
Create a dictionary (set/hashmap) with the strings as keys and the behaviour as value.
Using behaviour as values can be done in two ways:
Update: I found this article that might be what you're looking for: http://www.dreamincode.net/forums/topic/38412-the-command-pattern-c/
Upvotes: 1
Reputation: 56078
Here are the things to do in order of preference:
else if
clause inside it. This is the preferred option as your current strategy is a widely recognized symptom of poor design, and this is the suggested remedy.::std::map< ::std::string, void (*)(Window *pWindow)>
. This will allow you to look up the function to call in a map, which is much faster and easier to add to. This will also require you to split each else if
clause into its own function.::std::map< ::std::string, int>
. This will let you look up an integer for the corresponding string and then you can switch
on the integer.There are other refactoring strategies to use that more closely resemble option 1 here. For example,if you can't add a method to the Window
class, you can create an interface class that has the needed method. Then you can make a function that uses dynamic_cast
to figure out if the object implements the interface class and call the method in that case, and then handle the few remaining cases with your else if
construct.
Upvotes: 1
Reputation: 300199
What you ask for is possible, it's also unlikely to be a good solution to your problem.
Effectively the if/else if/else chain is ugly, the first solution that comes to mind will therefore to use a construct that will lift this, an associative container comes to mind and the default one is obviously std::unordered_map
.
Thinking on the type of this container, you will realize that you need to use the typename as the key and associate it to a functor object...
However there are much more elegant constructs for this. The first of all will be of course the use of a virtual
method.
class Base
{
public:
void execute() const { this->executeImpl(); }
private:
virtual void executeImpl() const { /* default impl */ }
};
class Derived: public Base
{
virtual void executeImpl() const { /* another impl */ }
};
It's the OO way of dealing with this type of requirement.
Finally, if you find yourself willing to add many different operations on your hierarchy, I will suggest the use of a well-known design pattern: Visitor. There is a variation called Acyclic Visitor which helps dealing with dependencies.
Upvotes: 0
Reputation: 19201
First of all use a higher level construct for strings like std::string
.
Second, if you need to check the type of the window your design is wrong.
Use the Liskov substitution principle to design correctly.
It basically means that any of the derived Window
objects can be replaced with it's super class.
This can only happen if both share the same interface and the derived classes don't violate the contract provided by the base class.
If you need some mechanism to apply behavior dynamically use the Visitor Pattern
Upvotes: 7
Reputation: 106236
You might try putting all your typeid(...).name() values in a map, then doing a find() in the map. You could map to an int that can be used in a switch statement, or to a function pointer. Better yet, you might look again at getting a virtual function inside each of the types that does what you need.
Upvotes: 0