Looks nice, but if the main point of Effects is to apply (and de-apply) StatModifiers, why not just have Effects contain a list of Stat/value pairs, so you don't have to implement start_effect and remove_effect each time you define a new Effect?
Main point of effects is to give total flexibility on implementing various effects that can affect character - permanent curses, diseases, poisons, buffs and debuffs, spells - so these functions are just hooks that writer of effect uses for a starting/ending point of an effect. This goes way beyond stat modifiers, so I wanted to keep stats and effects separated, because some effects won't even touch stats but change appearance of character, modify it's behavior and so on. The effect could for example do this:
print("You slowly turn into a frog!");
old_model = target->get_player_model();
print("You turn back into " + old_model->get_race() + "!");
Though I guess it's a good idea for a base effect that only affects stats So instead of creating separate Effect classes I could write StatChangeEffect() and just pass array of stats to affect, without the need to care about adding/removing modifiers for each one. But the general idea is for the effect class to be as flexible as possible in terms of how it affects target.