[Exceptional C++ Style] Item 18 - Virtuality

Herb Sutter hsutter at microsoft.com
Sat Jan 8 18:28:46 EST 2005


Good thread. Just to jump in at a random point:

Kevlin wrote:
> Good summary. However, in terms of the content of what is being
> summarised I disagree strongly with this. It is pure supposition and
I'm
> afraid that Herb and others have yet to demonstrate that this is a
> reasonable guideline either from first principles or in practice. As a
> pattern it is perhaps a dysfunctional one, but it would be mistaken to
> put it forward as a practice with the same pedigree as other
practices.
> 
> If one takes the time to analyse where the supposed benefits are, it
> becomes clear that in all cases NVI is either an inferior solution
> compared to another (eg interception) or an architectural
misconception.

I'm curious about this. Can you elaborate with examples?

In particular, NVI has been rediscovered several times, and in
particular WinFX has perhaps unique needs -- shipping a large
platform-level framework that will be heavily extended, so that once we
ship we are extremely constrained about the kinds of changes you can
make to base classes. For example, if you expose a public virtual
function and ship that way, you can't ever (easily) retrofit
instrumentation or other pre- and post-actions around the virtual call.
(One common reason to do that, by the way, is to catch all exceptions
and have an exception firewall where exceptions from a user's virtual
override won't escape. Only you won't do that on all virtual calls, and
you won't know until release 2 that you want it on additional ones you
didn't put it on at first. The other common reasons include the usual
ones to enforce pre- and post-conditions, to instrument performance, to
log, etc. The point is that you're calling code you don't control and
it's sane to have a boundary where you don't have your clients bypassing
you and calling that unknown code directly without having any chance to
get/stay in between.)

NVI is certainly viewed here as having been an important tool to help
WinFX's versioning robustness. Of course, I'm sure there are other
alternatives so I'm curious which ones Kevlin has found more applicable
for such framework cases. The problem exists, if to a lesser degree, for
even for internal frameworks if they are built by a different group in
the same company and don't release together as a unit with all the code
that uses them.

> Of the frameworks that have used it, almost all would benefit from
> better alternative solutions -- it is worth noting that the main
> examples in the standard library (I/O streams and locales) are not
> exactly examplars of clear and appropriate design.

Sure; I've been known to criticize the stdlib design. :-)

I cite that only as an example of how experts who didn't consciously
have NVI in mind, but instead started with "we want code X to work" use
cases, ended up doing NVI. (I'd add, "just like ADL," but maybe that's
still controversial. ;-) ) And the stdlib isn't alone.

> the more I looked at what the
> context and forces were, the less applicable the solution appeared to
> be. I could always see a better design or see a deeper root cause that
> should be addressed. In most cases it is a solution looking for a
> problem. It sometimes takes a more architectural perspective to see
why
> NVI is not a generally useful pattern. There is often too much focus
on
> language features when we formulate advice, and not enough on
> understanding the real design issues. The only place that NVI has any
> home is in the middle layer of a well-structured class hierarchy,
> between the fully abstract roots and the fully concrete leaves.

That is certainly its sweet spot.

Herb





More information about the Effective-cpp mailing list