0

I am attempting to develop a way in C++ to determine if a pointer to a class with virtual methods is a particular type of subclass using some form of RTTI.

Here are some example classes:

class Base {
public:
  virtual void foo() = 0;
};

class A : public Base {
public:
  void foo() override;
};

class B : public Base {
public:
  void foo() override;
};

class BB : public B {
public:

};

My goal is to determine the type of an instance of the root class (in this example Base) and use this to "route" this instance to a particular "handler" function. For example, I would have a table of std::type_index and std::function pairs. If the run-time type of the class passed in matches a type in the table, it calls the associated function with that instance.

Ideally, this would work using any level of inheritance. For example, using the classes above, let's say I have the following (conceptual) table

Type | Function
---------------
A    | fooA()
B    | fooB()

If I pass in an instance of the BB class (as a Base*), it should be "routed" to fooB because BB is a subclass of B.

In my research, I found the following: How do I check if an object's type is a particular subclass in C++? where the accepted answer says "You really shouldn't." However, in my case, I don't see another way to do this.

I hope that this makes sense. Please let me know if there is a better way to think about/achieve what I am trying to do.

Thanks

Patrick Wright
  • 1,401
  • 7
  • 13
  • 3
    You might be looking for a [Visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern). Are you allowed to modify any of these classes? – Igor Tandetnik Jan 27 '21 at 02:19
  • @IgorTandetnik I am writing all the classes, so yes, I am free to modify them how I want. – Patrick Wright Jan 27 '21 at 02:21
  • Are none of the answers you linked suitable? – Galik Jan 27 '21 at 02:25
  • 1
    "*My goal is to determine the type of an instance of the root class (in this example Base) and use this to "route" this instance to a particular "handler" function.*" - that really goes against the goal of what polymorphism strives for. If you design your `virtual` methods properly, the caller shouldn't care what type of object the methods are being called on. Also, think of what would happen if you had a class that derived from BOTH `A` and `B`. Your little table would fall apart trying to figure out which handler to use. – Remy Lebeau Jan 27 '21 at 02:29
  • That being said, if you really want to know if a given object is of a given type, that is what [`dynamic_cast`](https://en.cppreference.com/w/cpp/language/dynamic_cast) is meant for, eg: `Base *base = ...; if (A *a = dynamic_cast(base)) { fooA(a); } if (B *b = dynamic_cast(base)) { fooB(b); } ...` – Remy Lebeau Jan 27 '21 at 02:32
  • @RemyLebeau That makes sense, I didn't think of those complicated cases. I am wondering if it would be better to step back an look at my goal to do something simpler. Perhaps a virtual id() method would work. Then my table can contain mappings between IDs and handlers. All I would have to do is call the id() method then and do a table search. – Patrick Wright Jan 27 '21 at 02:38
  • A virtual id() method is one way. Another way is to use just a virtual destructor (to force generation of virtual method tables) and use [typeid](https://en.cppreference.com/w/cpp/language/typeid) / [std::type_index](https://en.cppreference.com/w/cpp/types/type_index) for this map. – Scheff's Cat Jan 27 '21 at 06:13
  • _"However, in my case, I don't see another way to do this."_ - you could've made the `foo` handler a virtual method of `Base` and call it like `p->foo()` no matter which instance `p` is pointing to. – Igor G Jan 27 '21 at 06:38

0 Answers0