C++ Vastly Different Derived Classes - Virtual methods? A cast? - c++

I have a class hierarchy with lots of shared member functions in a base class, and also a large number of unique member functions in two derived classes:
class Scene {
public:
void Display();
void CreateDefaultShapes();
void AddShape(Shape myShape);
// lots more shared member functions
}
Class AnimatedScene : public Scene {
public:
void SetupAnimation();
void ChangeAnimationSpeed(float x, float y);
// lots of member functions unique to animation
}
Class ControllableScene : public Scene {
public:
void ConfigureControls();
void MoveCamera(float x, float y, float z);
void Rotate(float x, float y, float z);
// lots of member functions unique to a controllable scene
}
Not surprisingly, this doesn't work:
Scene myScene;
myScene.SetupAnimation();
What is the correct solution to this problem? Should I make all of the derived member functions virtual and add them to the base? Should I use a cast when calling SetupAnimation()? Is there a more clever design that solves this problem?
Note: I receive myScene from elsewhere and can't simply declare it as AnimatedScene when I instantiate it.
Edit: I've added a couple more member functions to illustrate the point. A small handful of initialization functions definitely lend themselves to simply using virtual.

You can cast it, preferably using static_cast. The least preferable option. If you are casting things, it usually means your design needs more thought
If you have a particular function/class that needs one or the other, declare the input as the type you need, which more accurately communicates the requirements of the function or class
If the function needs to be generic, and those methods don't require any input, then you could define a virtual method in the parent class, say init, which in the derived classes call the correct methods to set up the instance.

I have a similar problem in my compiler project, where the AST (Abstract Syntax Tree) is constructed from the statements, so while(x != 0) { if (a == b) x = 0; } would construct a whileAST with a binaryExpr inside it, then a blockAST with the ifAST, and so on. Each of these have some common properties, and a lot of things that only apply when you actually do something specific to that part. Most of the time, that is solved by calling a generic (virtual) member function.
However, SOMETIMES you need to do very specific things. There are two ways to do that:
use dynamic_cast (or typeid + reinterpret_cast or static cast).
Set up dozens of virtual member functions, which mostly are completely useless (doesn't do anything or return an "can't do that" indication of some sort)
In my case, I choose the first one. It shouldn't be the common case, but sometimes it is indeed the right thing to do.
So in this case, you'd do something like:
AnimatedScene *animScene = dynamic_cast<AnimatedScene*>(&scene);
if (!animScene)
{
... do something else, since it's not an AnimatedScene ...
}
animScene->SetupAnimation();

I am not yet able to comment, which is what I really wanted to do, but I am also interested in figuring this out as well.
A few months ago I had a similar problem. What I can tell you is that you can use typeid operator to figure out what type the object is, like so:
int main()
{
scene* ptr = new AnimatedScene();
if (typeid(*ptr) == typeid(AnimatedScene))
{
cout<<"ptr is indeed a animatedScene"<<endl;
AnimatedScene* ptr2 = (AnimatedScene*)(ptr);
ptr2->SetupAnimation();
}
else
{
cout<<"not a animatedscene!!!"<<endl;
}
}
This works, you'll then be able to use ptr2 to access the animatedScene's unique members.
Notice the use of pointers, you can't use the objects directly, due to something called "object slicing" when playing with polymorphism: https://en.wikipedia.org/wiki/Object_slicing
Like you I have heard something about the use of typeid and thus, casting being a bad idea, but as to why, I cannot tell you. I am hoping to have a more experienced programmer explain it.
What I can tell you is that this works without problems in this simple example, you've avoided the problem of declaring meaningless virtual functions in the basetype.
Edit: It's amazing how often I forget to use google: Why is usage of the typeid keyword bad design?
If I understand mr Bolas correctly, typeid incentivizes bad coding practices. However, in your example you want to access a subtypes non-virtual function. As far as I know, there is no way of doing that without checking type at compiletime, ie typeid.

If such problem arises with your hierarchy that proves that hierarchy was too generalized. You might want to implement interfaces pattern, if class have certain functionality, it would inherit an interface that defines that functionality.

Proven that dogs are animals, do all animal but dogs fail to bark, or do only dogs bark?
The first approach lead to a class animal failing all the verses of the entire zoo, implemented one-by one in each animal. And in particular class dog will override just bark().
In this approach animal becomes a sort of "god object" (knows everything), requiring to be constantly updated every time something new is introduced, and requiring It's entire "universe" to be re-created (recompile everything) after it.
The second approach requires first to check the animal is a dog (via dynamic cast) and then ask it to bark. (or check for cat before asking a mieow)
The trade-off will probably consist in understanding how frequent is the possibility you have to check a bark out of its context (not knowing which animal are you deal with), how to report a fail, and what to do in case of such fail.
In other words, the key driver is not the bark, but the context around it inside your program.

//Are you trying to do something like this?
class Scene{
public:
virtual void Display()=0; //Pure virtual func
};
class AnimatedScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class AnimatedScene" <<std::endl;
}
};
class ControllableScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class ControllableScene" <<std::endl;
}
};
int main(){
AnimatedScene as;
ControllableScene cs;
Scene *ex1 = &as;
Scene *ex2 = &cs;
ex1->Display();
ex2->Display();
return 0;
}

Related

avoid vtable mixup in c++ variadic template inheritance

I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.
First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.
You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.

What is the advantage of using dynamic_cast instead of conventional polymorphism?

We can use Polymorphism (inheritance + virtual functions) in order to generalize different types under a common base-type, and then refer to different objects as if they were of the same type.
Using dynamic_cast appears to be the exact opposite approach, as in essence we are checking the specific type of an object before deciding what action we want to take.
Is there any known example for something that cannot be implemented with conventional polymorphism as easily as it is implemented with dynamic_cast?
Whenever you find yourself wanting a member function like "IsConcreteX" in a base class (edit: or, more precisely, a function like "ConcreteX *GetConcreteX"), you are basically implementing your own dynamic_cast. For example:
class Movie
{
// ...
virtual bool IsActionMovie() const = 0;
};
class ActionMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return true; }
};
class ComedyMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return false; }
};
void f(Movie const &movie)
{
if (movie.IsActionMovie())
{
// ...
}
}
This may look cleaner than a dynamic_cast, but on closer inspection, you'll soon realise that you've not gained anything except for the fact that the "evil" dynamic_cast no longer appears in your code (provided you're not using an ancient compiler which doesn't implement dynamic_cast! :)). It's even worse - the "self-written dynamic cast" approach is verbose, error-prone and repetitve, while dynamic_cast will work just fine with no additional code whatsoever in the class definitions.
So the real question should be whether there are situations where it makes sense that a base class knows about a concrete derived class. The answer is: usually it doesn't, but you will doubtlessly encounter such situations.
Think, in very abstract terms, about a component of your software which transmits objects from one part (A) to another (B). Those objects are of type Class1 or Class2, with Class2 is-a Class1.
Class1
^
|
|
Class2
A - - - - - - - -> B
(objects)
B, however, has some special handling only for Class2. B may be a completely different part of the system, written by different people, or legacy code. In this case, you want to reuse the A-to-B communication without any modification, and you may not be in a position to modify B, either. It may therefore make sense to explicitly ask whether you are dealing with Class1 or Class2 objects at the other end of the line.
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
if (typeid(object) == typeid(Class2))
{
additionalSpecialHandlingForClass2(dynamic_cast<Class2 &>(object));
}
}
Here is an alternative version which does not use typeid:
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
Class2 *ptr = dynamic_cast<Class2 *>(&object);
if (ptr != 0)
{
additionalSpecialHandlingForClass2(*ptr);
}
}
This might be preferable if Class2 is not a leaf class (i.e. if there may be classes further deriving from it).
In the end, it often comes down to whether you are designing a whole system with all its parts from the beginning or have to modify or adapt parts of it at a later stage. But if you ever find yourself confronted with a problem like the one above, you may come to appreciate dynamic_cast as the right tool for the right job in the right situation.
It allows you to do things which you can only do to the derived type. But this is usually a hint that a redesign is in order.
struct Foo
{
virtual ~Foo() {}
};
struct Bar : Foo
{
void bar() const {}
};
int main()
{
Foo * f = new Bar();
Bar* b = dynamic_cast<Bar*>(f);
if (b) b->bar();
delete f;
}
I can't think of any case where it's not possible to use virtual functions (other than such things as boost:any and similar "lost the original type" work).
However, I have found myself using dynamic_cast a few times in the Pascal compiler I'm currently writing in C++. Mostly because it's a "better" solution than adding a dozen virtual functions to the baseclass, that are ONLY used in one or two places when you already (should) know what type the object is. Currently, out of roughly 4300 lines of code, there are 6 instances of dynamic_cast - one of which can probably be "fixed" by actually storing the type as the derived type rather than the base-type.
In a couple of places, I use things like ArrayDecl* a = dynamic_cast<ArrayDecl*>(type); to determine that type is indeed an array declaration, and not someone using an non-array type as a base, when accessing an index (and I also need a to access the array type information later). Again, adding all the virtual functions to the base TypeDecl class would give lots of functions that mostly return nothing useful (e.g. NULL), and aren't called except when you already know that the class is (or at least should be) one of the derived types. For example, getting to know the range/size of an array is useless for types that aren't arrays.
No advantages really. Sometimes dynamic_cast is useful for a quick hack, but generally it is better to design classes properly and use polymorphism. There may be cases when due to some reasons it is not possible to modify the base class in order to add necessary virtual functions (e.g. it is from a third-party which we do not want to modify), but still dynamic_cast usage should be an exception, not a rule.
An often used argument that it is not convenient to add everything to the base class does not work really, since the Visitor pattern (see e.g. http://sourcemaking.com/design_patterns/visitor/cpp/2) solves this problem in a more organised way purely with polymorphism - using Visitor you can keep the base class small and still use virtual functions without casting.
dynamic_cast needs to be used on base class pointer for down cast when member function is not available in base class, but only in derived class. There is no advantage to use it. It is a way to safely down cast when virtual function is not overridden from base class. Check for null pointer on return value. You are correct in that it is used where there is no virtual function derivation.

Inheritance, a parent accesing children in c++

I am making a chess game and when I click on a square I want to know what piece is there. Since there are more than 1 type of pieces it would be annoying to have more variables in the Square structure.
So I have though about a class named Piece which is the parent of each type of Piece.
Example.
class Pawn : public Piece
I want to achieve a Square structure that looks something like this :
struct Square { Piece *piece };
Now, I want to initialize the piece variable like this :
piece = new Pawn(); // or what type of piece it should be.
My problem is that by doing this I can still only access Piece's class functions and not the Pawns ones.
How do I achieve such thing as having only 1 parent which can access everything his children have?
You can make virtual functions.
Define virtual function in base class and override it in child class.
For Example
class Base
{
public:
const char* SayHi() { return "Hi"; } // a normal non-virtual function
virtual const char* GetName() { return "Base"; } // a normal virtual function
virtual int GetValue() = 0; // a pure virtual function
};
class Child:public Base{
{
int GetValue(){
//write any code here
//return something;
}
}
For more refer to link:
http://www.learncpp.com/cpp-tutorial/126-pure-virtual-functions-abstract-base-classes-and-interface-classes/
The best approach by far is try avoiding this situation: can you make the interface of the Piece uniform for all subclasses? If this can be done, choose this design without much hesitation, because what I describe below is a lot more complex, and also much harder to read.
Since you cannot access member functions of derived types through a pointer to the base type, you need to work around this in one of several ways:
Use dynamic_cast<Derived> - This is very simple, but extremely fragile. Changes to the inheritance structure can break an approach based on frequent dynamic casts.
Use VisitorPattern - This is a good choice when the class structure is not expected to change (you're in luck here: the list of types that you plan to model has not changed in many centuries)
Use Runtime Type Information and maps of function objects - This approach is very flexible, but it is somewhat hard to read. Lambdas of C++11 make it easier, though.

Permanently Downcast c++ Pointer

So this is probably a weird question, but I have a reasonably good reason for asking.
The gist of my question is, given an example with two levels of derivation on a class hierarchy:
Main Base Class:
class Animal
{
virtual void Draw() = 0;
};
Derived Class:
class Dog : public Animal
{
virtual void Draw()
{
// draw a generic dog icon or something...
}
};
Further Derivation:
class Corgi : public Dog
{
virtual void Draw()
{
// draw a corgi icon...
}
};
Now, I'd love to be able to, from within the Corgi class, permanently downcast the 'this' pointer to a Dog pointer and then pass it off somewhere else as an Animal. This other place will then be able to call the Draw function and get the Dog method, not the virtual Corgi method. I know this is strange, but again, I have a vaguely legitimate reason for wanting to do it.
I've tried all the different casting operators and haven't had any luck, but maybe there is a consistent way of pulling this off? In the past I've caused myself trouble by not properly using dynamic_cast which resulted in a similar state for a pointer. Perhaps this time I can use that to my advantage?
Edit:
Perhaps the above example doesn't illustrate clearly the what I'm trying to achieve, so I'll elaborate with my real goal.
I'm trying to achieve a shorthand for registering base class implementations that link into a scripting system I've been using for a while. The scripting system relies on a base class IScriptContext to facilitate access to real-code functions and member variable access. Internally base classes register their member function addresses and member variable addresses which are later dispatched/accessed through lookup tables. I'm in the process of adding proper support for class derivation hierarchies to the scripting system, and I figured being able to isolate the base class versions of these interfaces would help save time and make the whole process cleaner for me when it comes time to register available base classes with the script interpreter. There are other ways to achieve this, such as registering class specific function pointers for each required method for each available base class (e.g. this->Dog::CallFunction, this->Dog::SetMember, this->Dog::GetMember.) However, I figured using an interface would allow me to modify things a bit easier down the road if I ever needed to.
I hope all of that makes some kind of sense.
Thanks!
You have a Corgi object. You can:
Treat it as a Dog object everywhere by using the Dog:: qualifier to all calls (e.g. ptr->Dog::draw();). This loses you virtual dispatch, and is almost certainly not what you want from how your question reads.
Actually construct a new Dog object from your Corgi. Just do this with a normal static_cast as you'd convert any other type or let implicit conversion take over (e.g. Corgi c; Dog d(c);).
These are the options available to you. To want to retain a Corgi but automatically pretend everywhere that it's a Dog is neither reasonable nor legitimate, so the language does not provide for it.
Let me start off by saying your design looks faulty.
You can however explicitly say which function in a hierarchy you want to call:
Corgi* corgi = new Corgi;
corgi->Dog::draw();
This will call the draw method from Dog, not from Corgi. (I hope I understood correctly what you're asking).
Tomalak has already outlined two of the main choices available to you:
use qualified calls, or
construct a Dog as a Dog copy of your Corgi.
In addition to these, you can
use a simple wrapper
e.g.
class LooksLikeDog
: public Dog
{
private:
Dog* realObject_;
LooksLikeDog( LooksLikeDog const& ); // No such.
LooksLikeDog& operator=( LooksLikeDog const& ); // No such.
public:
LooksLikeDog( Dog& other )
: realObject_( &other )
{}
// Just for exposition: not implementing this does the same.
virtual void draw() override { Dog::draw(); }
// Example of other method that may need to be implemented:
virtual void bark() override { realObject_->bark(); }
};
But the best solution is most probably to fix your design. ;-)
Implement Corgi draw function and call your parent's implementation:
virtual void Corgi::Draw()
{
Dog::draw();
}

Why doesn't C++ allow you to request a pointer to the most derived class?

(This question should probably be answered with a reference to Stroustrup.)
It seems extremely useful to be able to request a pointer to the most derived class, as in the following:
class Base { ... };
class DerivedA { ... };
class DerivedB { ... };
class Processor
{
public:
void Do(Base* b) {...}
void Do(DerivedA* d) {...}
void Do(DerivedB* d) {...}
};
list<Base*> things;
Processor p;
for(list<Base*>::iterator i=things.begin(), e=things.end(); i!=e; ++i)
{
p.Do(CAST_TO_MOST_DERIVED_CLASS(*i));
}
But this mechanism isn't provided in c++. Why?
Update, Motivating Example:
Suppose instead of having Base and Derived and Processor, you have:
class Fruit
class Apple : public Fruit
class Orange: public Fruit
class Eater
{
void Eat(Fruit* f) { ... }
void Eat(Apple* f) { Wash(f); ... }
void Eat(Orange* f) { Peel(f); ... }
};
Eater me;
for each Fruit* f in Fruits
me.Eat(f);
But this is tricky to do in C++, requiring creative solutions like the visitor pattern. The question, then, is: Why is this tricky to do in C++, when something like "CAST_TO_MOST_DERIVED" would make it much simpler?
Update: Wikipedia Knows All
I think Pontus Gagge has a good answer. Add to it this bit from the Wikipedia entry on Multiple Dispatch:
"Stroustrup mentions that he liked the concept of Multi-methods in The Design and Evolution of C++ and considered implementing it in C++ but claims to have been unable to find an efficient sample implementation (comparable to virtual functions) and resolve some possible type ambiguity problems. He goes on to state that although the feature would still be nice to have, that it can be approximately implemented using double dispatch or a type based lookup table as outlined in the C/C++ example above so is a low priority feature for future language revisions."
For background, you can read a little summary about Multi-Methods, which would be better than a call like the one I mention, because they'd just work.
Probably because that's what virtual functions do for you instead. The implementation of the virtual function that is nearest the most-derived class will be called when you invoke it through a base class pointer or reference.
Firstly, C++ does allow you to request a pointer to a most derived class in numerical terms (i.e. just the numerical value of the address). This is what dynamic_cast to void* does.
Secondly, there's no way to obtain a pointer to the most derived class in therms of exact type of the most derived class. In C++ casts work with static types, and static type is a compile-time concept. Type-based function overloading is also a compile-time process. The exact most derived type is not known at compile-time in your case, which is why cannot cast to it and can't resolve overloading on it. The request to have such a cast makes no sense in the realm of C++ language.
What you are trying to implement (if I understood your intent correctly), is implemented by completely different means, not by a cast. Read about double dispatch, for one example.
Because the type of i is not determinable at compile time. Therefore the compiler would not know which function call to generate. C++ only supports one method of dynamic dispatch that is the virtual function mechanism.
What you are suggesting would be equivalent to a switch on the runtime type, calling one of the overloaded functions. As others have indicated, you should work with your inheritance hierarchy, and not against it: use virtuals in your class hierarchy instead of dispatching outside it.
That said, something like this could be useful for double dispatch, especially if you also have a hierarchy of Processors. But how would the compiler implement it?
First, you'd have to extract what you call 'the most overloaded type' at runtime. It can be done, but how would you deal with e.g. multiple inheritance and templates? Every feature in a language must interact well with other features -- and C++ has a great number of features!
Second, for your code example to work, you'd have to get the correct static overload based on the runtime type (which C++ does not allow as it is designed). Would you like this to follow the compile time lookup rules, especially with multiple parameters? Would you like this runtime dispatch to consider also the runtime type of your Processor hierarchy, and what overloads they have added? How much logic would you like the compiler to add automatically into your runtime dispatcher? How would you deal with invalid runtime types? Would users of the feature be aware of the cost and complexity of what looks like a simple cast and function call?
In all, I´d say the feature would be complex to implement, prone to errors both in implementation and usage, and useful only in rare cases.
It's called using a virtual function call. Pass the processor* into DerivedA/B's virtual method. Not the other way around.
There is no mechanism provided because it's totally unnecessary and redundant.
I swear, I fielded this exact question about a day or two ago.
In C++ overload resolution happens at compile time. Your example would require determining the real type of *i at runtime. For it to be done at runtime would require a runtime type check, and because C++ is a performance oriented language it purposefully avoids this cost. If you really wanted to do this (and I'd be curious to see a more realistic example) you could dynamic_cast to the most derived class, then if that fails to the second most derived class, and so on, but this requires knowing the class hierarchy up front. And knowing the full hierarchy up front maybe impossible -- if the DerivedB class is in a public header, it's possible another library uses it and has made an even more derived class.
You're looking for double dispatch. It can be done in C++, as shown at that link, but it's not pretty, and it basically involves using two virtual functions calling each other. If you can't modify some of the objects in your inheritance tree, you may not be able to use this technique either.
This is not possible in C++, but what you want to achieve is easily doable using the Visitor design pattern:
class Base
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class DerivedA
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class DerivedB
{
virtual void accept(BaseVisitor& visitor) { visitor.visit(this); }
};
class BaseVisitor
{
virtual void visit(Base* b) = 0;
virtual void visit(DerivedA* d) = 0;
virtual void visit(DerivedB* d) = 0;
};
class Processor : public BaseVisitor
{
virtual void visit(Base* b) { ... }
virtual void visit(DerivedA* d) { ... }
virtual void visit(DerivedB* d) { ... }
};
list<Base*> things;
Processor p;
for(list<Base*>::iterator i=things.begin(), e=things.end(); i!=e; ++i)
{
(*i)->visit(p);
}
Why doesn't C++ have it? Perhaps the creators never thought about it. Or perhaps they didn't consider it suitable or useful enough. Or perhaps there were problems with actually trying to do it in this language.
On that last possibility, here's a thought experiment:
Lets say the this feature exists so that the compiler will write code that examines the dynamic type pointed to and calls the appropriate overload. Now lets also say a separate portion of the code has class DerivedC : Base {...};. And say that the corresponding Processor::Do overload is not added.
Given all of that, what should the program do when it tries to choose the appropriate overload? This discrepancy cannot be caught at compile-time. Should it try to climb the class hierarchy to find a function that matches a base class? Should it throw a special exception? Should it just crash? Is there some other possibility? Is there actually any reasonable choice that the compiler could make on its own without knowing the intention of your code and class hierarchy?
Yes, writing such functionality yourself would be susceptible to the same problem, but there the programmer has total control to choose the behavior, not the compiler.
C++ interprets data in the context of the associated type. When you store an instance of DerivedA* or DerivedB* in a list, that associate type must necessarily be Base*. This means that the compiler itself can no longer determine that those are pointers to one of the subclasses rather than the base class. While in theory you could cast to a LESS derived class by looking at the associated type's inheritance, the information needed to do what you want simply isn't available at compile-time.