[23.2] That last FAQ confuses me. Is it a different strategy from the other ways to use virtual functions? What's going on?
Yes, it is a different strategy. Yes, there really are two different basic
ways to use virtual functions:
- Suppose you have the situation described in the previous FAQ: you
have a method whose overall structure is the same for each derived class, but
has little pieces that are different in each derived class. So the algorithm
is the same, but the primitives are different. In this case you'd write the
overall algorithm in the base class as a public method (that's sometimes
non-virtual), and you'd write the little pieces in the derived classes. The
little pieces would be declared in the base class (they're often protected,
they're often pure virtual, and they're certainly virtual), and
they'd ultimately be defined in each derived class. The most critical
question in this situation is whether or not the public method containing
the overall algorithm should be virtual. The answer is to make it virtual
if you think that some derived class might need
to override it.
- Suppose you have the exact opposite situation from the previous
FAQ, where you have a method whose overall structure is different in each
derived class, yet it has little pieces that are the same in most (if not all)
derived classes. In this case you'd put the overall algorithm in a public
virtual that's ultimately defined in the derived classes, and the little
pieces of common code can be written once (to avoid code duplication) and
stashed somewhere (anywhere!). A common place to stash the little pieces is
in the protected part of the base class, but that's not necessary and it
might not even be best. Just find a place to stash them and you'll be fine.
Note that if you do stash them in the base class, you should normally make
them protected, since normally they do things that public users don't
need/want to do. Assuming they're protected, they probably shouldn't be
virtual: if the derived class doesn't like the behavior in one of them, it
doesn't have to call that method.
For emphasis, the above list is a both/and situation, not an either/or
situation. In other words, you don't have to choose between these two
strategies on any given class. It's perfectly normal to have method f()
correspond to strategy #1 while method g() corresponds to strategy #2. In
other words, it's perfectly normal to have both strategies working in the same
class.