C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 31:
[31.3] What's the difference between virtual data and dynamic data?

The easiest way to see the distinction is by an analogy with virtual functions: A virtual member function means the declaration (signature) must stay the same in derived classes, but the definition (body) can be overridden. The overriddenness of an inherited member function is a static property of the derived class; it doesn't change dynamically throughout the life of any particular object, nor is it possible for distinct objects of the derived class to have distinct definitions of the member function.

Now go back and re-read the previous paragraph, but make these substitutions:

  • "member function" "member object"
  • "signature" "type"
  • "body" "exact class"

After this, you'll have a working definition of virtual data.

Another way to look at this is to distinguish "per-object" member functions from "dynamic" member functions. A "per-object" member function is a member function that is potentially different in any given instance of an object, and could be implemented by burying a function pointer in the object; this pointer could be const, since the pointer will never be changed throughout the object's life. A "dynamic" member function is a member function that will change dynamically over time; this could also be implemented by a function pointer, but the function pointer would not be const.

Extending the analogy, this gives us three distinct concepts for data members:

  • virtual data: the definition (class) of the member object is overridable in derived classes provided its declaration ("type") remains the same, and this overriddenness is a static property of the derived class
  • per-object-data: any given object of a class can instantiate a different conformal (same type) member object upon initialization (usually a "wrapper" object), and the exact class of the member object is a static property of the object that wraps it
  • dynamic-data: the member object's exact class can change dynamically over time

The reason they all look so much the same is that none of this is "supported" in C++. It's all merely "allowed," and in this case, the mechanism for faking each of these is the same: a pointer to a (probably abstract) base class. In a language that made these "first class" abstraction mechanisms, the difference would be more striking, since they'd each have a different syntactic variant.