I agree and think it's a good idea to derive from a base enemy class. Then you can tailor each enemy as you see fit in derived classes. The more functionality you put in the base, the more you gain in the derived. But keep the base class functions and members very generic and not tailored to any one type of enemy.
For instance all enemies must move and all of them prob follow a vector. All enemies must be able to go to waypoints, etc, etc.
I would keep my derivations to a maximum of 1 or possible 2 levels of inheritance (derive from base only once and once from derived) as multiple derivations will probably just serve to confuse and obfuscate the code.
This also allows you to specify an enemy manager class that contains a vector or list of enemies. Since you are deriving all enemies from a common base, if you make the list or vector that contains the base type you can add any object that has been derived from base. This makes managing the objects quite simple.
Now you can do this:
class CSpider:public CEnemy
std::vector<CEnemy *> m_vEnemies;
DWORD Add(CEnemy *pEnemy)
Spider *pBadDude=new Spider();