No, it is not possible.
The function which is called is chosen at compile-time. Lets say you have code like this:
Base &o = getSomeObject();
handle(o);
The compiler doesn't know the real type of o. It only knows that it is some subtype of Base
or Base
itself. This mean it will search for a function which acceppts objects of type Base
.
You could implement a check for the type yourself or use a map to store possible functions:
Base &o = getSomeObject();
functionMap[typeid(o)](o);
But typeid
does only work this whay if Base
is a polymorphic type. This mean it must have at least one virtual function. This brings us to the next section:
But you could use virtual functions.
Virtual functions are non-static member functions of classes which can be overridden. The right function is resolved at runtime. The following code would output Subt
instead of Base
:
class Base {
public: virtual std::string f() {return "Base"}
};
class Subt : public Base {
public: virtual std::string f() {return "Subt"}
};
int main() {
Subt s;
Base &b = s;
std::cout << b.f() << std::endl;
}
You can omit virtual
in the definition of Subt
. The function f()
is already defined as virtual in it's base class.
Classes with at least one virtual function (also called polymorphic types) are storing a reference to a virtual function table (also called vtable). This table is used to get the right function at runtime.
The problem in your question could be solved like this:
class Parent {
public:
virtual void handle() = 0;
};
class A : public Parent {
public:
void handle() override { /* do something for instances of A */ }
};
class B : public Parent {
public:
void handle() override { /* do something for instances of B */ }
};
class C : public Parent {
public:
void handle() override { /* do something for instances of C */ }
};
int main()
{
std::vector<std::unique_ptr<Parent>> children = {
std::make_unique<A>(),
std::make_unique<B>(),
std::make_unique<C>()};
for (const auto &child : children)
child->handle();
}
Note about compatibility: The keywords auto
and override
are only available in C++11 and above. The range-based for loop and std::unique_ptr
is also available since C++11. The function std::make_unique
is available since C++14. But virtual function can be used with older versions, too.
Another hint:
Polymorphism does only work with references and pointers. The following would call Base::f()
and not Subt::f()
:
Subt s;
Base b = s;
std::cout << b.f() << std::endl;
In this example b
will just contain a object of type Base
instead of Subt
. The object is just created at Base b = s;
. It may copy some information from s
but it isn't s
anymore. It is a new object of type Base
.