I don't think the number of descendants (in itself) is necessarily a problem.
But I question whether inheritance is likely an ideal way to implement this behavior anyway.
By putting the undo/redo at the base of the tree, you're asserting that everything that derives from it must also support undo/redo. That may not work well, however, with an existing hierarchy. In an existing hierarchy, you might well have a few fairly specific nodes that should support undo/redo, but that support is (at least more less) distinct from the existing hierarchy.
In a fair number of cases, it's also the context that determines whether something should support undo/redo, not the object itself. So, you may have some objects of a class that should support undo, but others that shouldn't.
There are a couple of fairly common ways of implementing undo/redo. The command pattern is one. And what you're talking about might be pretty much an implementation of Command (or not--you haven't given enough detail to be sure). To implement the Command pattern, your base class would define something like execute
and undo
methods, so anything derived from it will be able to do or undo it's "thing" on command. This does work, but tends to be fairly intrusive on the objects that need to support undo/redo. It also tends to have fairly tight coupling between the mechanism for saving/retrieving/restoring state, and the policy for the pattern(s) you do/don't support in doing so (so, for example, this often doesn't support things like "redo A, C, and D, but not B").
Another common method is the memento pattern. This is basically kind of a generic way of storing an object's internal state. You normally have an Originator (the thing you want to be able to undo/redo), a memento (the internal state itself) and a Caretaker, which gets and saves the memento, and handles actually saving and restoring Mementos to implement the undo/redo as needed. The advantage here is that it decouples the undo/redo implementation from the objects you want to be able to undo/redo. All the object needs to be able to do so produce or consume a memento, and deciding how/when to tell it to do that is up to the (entirely separate) caretaker class. This tends to make it easier to add support for non-linear undo/redo patterns, such as the one outlined above, of redoing A, C, and D, but skipping B.