There's certainly no problem with slicing --- your classes don't need vtables since they have no virtual functions, but even if they did have them, pass-by-reference doesn't copy the object and hence doesn't slice anything.
You can make virtual calls via references exactly as you can via pointers. So as far as I know there's no practical reason, it's for style only.
Perhaps it's to do with the fact that polymorphic objects are generally created by pointer with new
, and of course must be stored in containers by pointer (or smart pointer) since you can't have a container of references. It might then seem more consistent to manipulate them by pointer always.
Also, if you want to use OperateOnObject
in a standard algorithm like for_each
, then either it has to accept the element type of the container, which is a pointer, or else you have to wrap it in a function adaptor that does the dereference. Standard C++ doesn't have that adaptor, so it's a world of hassle to base your style on it.
Related: look what happens if OperateOnObject
takes a reference, and you iterate your vector using iterators:
for (vector<Base*>::iterator i = objects.begin(); i != objects.end(); ++i) {
OperateOnObject(**i);
}
The 20th time that double-indirection annoys or confuses you, you will change the signature of OperateOnObject
;-)
As an aside, some style guides warn against passing non-const references regardless of whether the type is a polymorphic base class, on the grounds you can't immediately tell the difference between pass-by-reference and pass-by-value when you're reading code at the call site. So they'd prefer OperateOnObject
to take a pointer anyway.
Personally I think that argument is a little weak -- a function's name should tell you roughly what it does, and in particular a statement like ChangeTheObject(my_object);
is not-so-subtly hinting to me that since it's not using any return value, it must change its argument. But I accept that if you follow a style properly, there's some benefit to clearly and consistently distinguishing mutators from pure functions.