Suppose you created a derived class, then replaced every instance of the base class in your program with that derived class. Did the resulting program behave the same? If not, then you have introduced some gotchas. These gotchas will probably be accounted for in the case of a class designed for inheritance (e.g. I've seen some classes designed for inheritance that actually have functions to check if other functions are implemented to allow for the case of them not even existing, e.g. file i/o classes that might be missing seek functionality). Since an abstract class is always going to have been designed with inheritance in mind but a concrete class might not, this could be unsafe.
The explanation above talks about the case where the resulting derived class is not fully compatible with the base class, which is dangerous. But what if it is fully compatible? In this case, some of the potential justifications for using inheritance (instead of composition) fall apart. We don't have any virtual functions or protected members (if we do, then I assume the class was designed for inheritance). Still, using inheritance in this case is probably pretty safe, though ensuring it really is fully compatible is tough. I'd rather use composition and be safe.