Skip to content

Public Virtual Methods: A Bad Idea

ADMIN | 26-04-2011

The answer for public methods is easy: if you think of the class as providing a set of services, it’s the clients of the services, i.e. the users of the class.

Hexagon pattern 1

When’s the last time you saw code like this?

Did you:

f00 code1

  1. A) Think nothing of it?

Or.

  1. B) Say to yourself, "Oops – whoever wrote that goofed"?

It’s probably pretty obvious from today’s title that my answer would be "B".

The abstract reason for this is that Foo::DoSomething() violates (the spirit of) the Single Responsibility Principle.

This can be seen by thinking about who the customers (I say "customer" because "client" is a loaded term) are of public methods, and who are the customers of virtual methods.

The answer for public methods is easy: if you think of the class as providing a set of services, it’s the clients of the services, i.e. the users of the class. The answer for virtual methods isn’t much harder: it’s the implementers of derived classes.

In other words, public method declarations are an interface mechanism for informing clients about the services of the class; virtual method declarations are an interface mechanism for telling implementers about the behaviors of the class which can be specialized.

Understanding the Challenges of Public Virtual

A public virtual method is trying to serve two masters who might have conflicting requirements – this is usually a bad idea, as can be seen by the predicament that the poor gentlemen below has found himself in.

The practical reason for answer "B" is a flow control issue: execution flow never passes through the base class when a virtual method is called. This means that the base class has absolutely no ability to enforce common behaviors among the derived classes.

This in turn often leads to a set of rules that must be remembered in order to correctly override the base class methods. For example, when’s the last time you saw this save idiom:

 f00 code2

Because Foo1::Save is virtual, the application requires the implementer of Boo1 to learn and remember to save the base class data.

This is a burden on the poor implementer (who often has to remember a different set of rules for each class) and a recipe for bugs when someone forgets something.

For More on How to Improve Engineering Design Flows:

The way to solve this problem is to split the responsibilities between two methods: A public method that clients call and a virtual method that implementers override.

f00 code3

In contrast to the Foo1 example, there is all sorts of good stuff going on in Foo2:

  • Implementers don’t need to remember to call the base class save – the base class saves its own data.
  • Because flow passes through the base class, standard input checking can be implemented in the base class method.
  • Pre- and post-operation contract checks can be performed in the base class method. This is especially important for the post-operation checks, because it can be used to ensure that implementers didn’t get subtle required behaviors wrong.
  • The virtual SaveSubClassData doesn’t need a base class implementation, so it can be declared pure (forcing implementers to realize that the need to write a method) without confusing implementers with the "pure virtual methods are allowed to have implementations" subtlety.
  • All of these attributes lead to cleaner, more robust code, and the underlying reason is that the different responsibilities are now properly segregated between appropriate methods.
 

Two subtleties:

1) You might have noticed that I declared Foo2::SaveSubClassData as private.

This is legal C++, and it’s preferred over declaring SaveSubClassData as protected.

The reason is that protected methods have a similar responsibility to public methods: they provide a set of services which derived classes can make use of. In other words, even derived classes should only call virtual methods through non-virtual base-class wrappers.

2) There is one exception to the above discussion.

The case where Foo is a pure interface class (analogous to a C# interface). By this I mean Foo has no data members, only pure virtual methods, and is used in a multiple-inheritance “mix-in” context to emulate the “implements” mechanism of e.g. C#.

The point of an interface class is that it’s a mechanism for client code to specify the services it requires; this is subtly different from the responsibility of public methods specifying the services the class supplies and corresponds to a single responsibility.

In particular, there’s no implementation code associated with an interface – control jumps straight to the implementer, which is exactly what happens with pure virtual methods.

You might also like...

5 Min read
CGM Modeler
Software components are like the stage crew at a big concert performance: the audience doesn’t see them, but their...
8 Min read
CGM Modeler
There’s a lot of confusion around what the terms additive manufacturing and 3D printing mean.
2 Min read
CGM Modeler
WRL files are an extension of the Virtual Reality Modeling Language (VRML) format . VRML file types enable browser...
Voxel model example
3 Min read
CGM Modeler
Voxels are to 3D what pixels are to 2D. Firstly -- let’s examine what pixels actually are. Everything you see on your...
Point_cloud_torus
2 Min read
CGM Modeler
Point-cloud modeling is typically used in the process of 3D scanning objects. Rather than defining surfaces through...
Polygonal Modeling
2 Min read
CGM Modeler
Polygonal (or polyhedral) modeling is the most common type of modeling for video games and animation studios. This type...
BREP Model example
2 Min read
CGM Modeler
BRep modeling, or Boundary Representation modeling, is, in CAD applications, the most common type of modeling. BRep is...
Construction site with crane and building-1
3 Min read
3D Software Development Kits
Digital twins are changing the way the construction industry manages large building projects and infrastructure...
3 Min read
3D Software Development Kits
There is a new wave of innovative processes and solutions that improve product production throughput, and enable...
3D Product Visualization.jpg
2 Min read
3D Software Development Kits
In the 3D modeling space, application developers face a number of challenges — getting to market on time, delivering...
General PMI
4 Min read
3D Software Development Kits
It has already been a year since release 2017 1.0, which saw the introduction of a number of innovative features aimed...
Large Tolerant  Vertex
3 Min read
3D Software Development Kits
boolean operation Boolean operations on individual bodies are common functions in 3D modeling. While simple in concept,...
3 Min read
3D Software Development Kits
In much the same way as physical design has moved from paper 2D drawings to 3D models in software, so has analysis....
2 Min read
3D Software Development Kits
Today was day one of Spatial Corp.’s 3D Insiders’ Summit 2016, an educational event that focuses on technical topics...
4 Min read
3D InterOp
Part and parcel with model-based engineering is model translation. Because the model is now the specification, accurate...
3 Min read
3D Software Development Kits
In case you missed the news this week, we announced the availability of Release 2017 1.0 for Spatial software...
2 Min read
3D Software Development Kits
Augmented World Expo 2016
4 Min read
3D Software Development Kits
Make or buy is an age old question for anyone building products, whether hardware or software. For example, for a...