EDIT: Splitting this topic off to a new topic because it is too disruptive where it is. Earlier discussion here.
"Public and virtual" -> Unnecessary if not inherited, necessary if inherited.
"Protected and non-virtual" -> What protection does that give?
Something seems to be going over my head here. Would you mind elaborating?
(Perhaps my question + your explanation should be split into its own thread in the General Programming subforum if the answer is technical)
Herb Sutter (the chair of the C++ committee) described it well several times over the years. The reasons to use virtual functions and the proper place for them is something worth frequent reminding.
Most experienced c++ programmers should be familiar with all four of these detailed guidelines.
Item 4 on the list covers this specific case. Seeing all the protected functions means the class is meant for inheritance, therefore it seems public and virtual is the rule.
Item 1 on the list is especially painful, and I try to educate game programmers when I see it. Back on one of my DS titles (remember: 66MHz, or 1 million cycles per frame) one of the leads decided to make some of the major classes have public virtual interfaces. Since he was fairly new to C++ coming from a C background and since the code sometimes did rely on polymorphic behavior, he was hard-pressed to be convinced differently. This seemed to be the C++ way of doing things: public virtual functions were found in a few libraries (not the C++ standard libraries, of course!) so he was convinced to use them.
Down the road a few weeks we were looking at profiles of the rapidly growing game. A large percentage (we couldn't be certain yet) of our CPU time was being consumed by virtual dispatch in final-optimized builds. Evidence in hand, it was easy to test and verify. In my test I refactored only two or three of the simplest ones (the ones with no variation in leaf classes) and recovered several percent of each frame's compute cycles.
It wasn't too difficult to change once he saw the problem. We removed the virtual functions from the public interface of several major base classes, sometimes creating a member variable that was modified during constructor, other times creating functions for the bits that needed to be dynamically overrriden, and we powered through the major offenders in the code base in about a day. IIRC we recovered about 8% of our CPU time with that simple change.
Overuse of virtual functions can quickly ruin game performance. An obvious symptom (if you are actually concerned about it) are a large number of zero-byte or four-byte functions in the symbol table. Usually these are virtual functions that do nothing; in many cases it is possible to completely eliminate the function call overhead.
As for the complications, you can call "delete pFoo" when the object has a private destructor. What you cannot do is call the destructor directly, which can be an issue with classes like shared_ptr or a custom memory managers. The solution there is to provide a deleter function, which is an optional parameter on shared_ptr and many custom memory managers that defaults to a template value of Foo::~Foo but can be customized with whatever you need.
Edited by frob, 20 March 2014 - 12:13 AM.
Adding notes at the beginning about splitting the topic.