FAQs in section [23]:
[23.1] Is it okay for a non-virtual function of the base class to call a virtual function?
Yes. It's sometimes (not always!) a great idea. For example, suppose
all Shape objects have a common algorithm for printing, but this algorithm
depends on their area and they all have a potentially different way to compute
their area. In this case Shape's area() method would necessarily
have to be virtual (probably pure virtual) but Shape::print()
could, if we were guaranteed no derived class
wanted a different algorithm for printing, be a non-virtual defined in
the base class Shape.
#include "Shape.h"
void Shape::print() const
{
float a = this->area(); // area() is pure virtual
...
}
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[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.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.3] When my base class's constructor calls a virtual function on its this object, why doesn't my derived class's override of that virtual function get invoked?
Because that would be very dangerous, and C++ is protecting you from that
danger.
The rest of this FAQ gives a rationale for why C++ needs to protect you from
that danger, but before we start that, be advised that you can get the
effect as if dynamic binding worked on the this object even during a
constructor via The Dynamic Binding
During Initialization Idiom.
First, here is an example to explain exactly what C++ actually does:
#include <iostream>
#include <string>
void println(const std::string& msg)
{ std::cout << msg << '\n'; }
class Base {
public:
Base() { println("Base::Base()"); virt(); }
virtual void virt() { println("Base::virt()"); }
};
class Derived : public Base {
public:
Derived() { println("Derived::Derived()"); virt(); }
virtual void virt() { println("Derived::virt()"); }
};
int main()
{
Derived d;
...
}
The output from the above program will be:
Base::Base()
Base::virt() // ← Not Derived::virt()
Derived::Derived()
Derived::virt()
The rest of this FAQ describes why C++ does the above. If you're
happy merely knowing what C++ does without knowing why, feel
free to skip this stuff.
The explanation for this behavior comes from combining two facts:
- When you create a Derived object, it first calls Base's
constructor. That's why it prints Base::Base() before
Derived::Derived().
- While executing Base::Base(), the this object is not yet
of type Derived; its type is still merely Base. That's why the call to
virtual function virt() within
Base::Base() binds to Base::virt() even though an override
exists in Derived.
Now some of you are still curious, saying to yourself, "Hmmmm, but I still
wonder why the this object is merely of type Base during
Base::Base()." If that's you, the answer is that C++ is protecting
you from serious and subtle bugs. In particular, if the above rule were
different, you could easily use objects before they were initialized,
and that would cause no end of grief and havoc.
Here's how: imagine for the moment that calling this->virt() within
Base::Base() ended up invoking the override Derived::virt().
Overrides can (and often do!) access non-static data members declared in the
Derived class. But since the non-static data members declared in Derived
are not initialized during the call to virt(), any use of them within
Derived::virt() would be a "use before initialized" error. Bang,
you're dead.
So fortunately the C++ language doesn't let this happen: it makes sure any
call to this->virt() that occurs while control is flowing through
Base's constructor will end up invoking Base::virt(), not the
override Derived::virt().
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.4] Okay, but is there a way to simulate that behavior as if dynamic binding worked on the this object within my base class's constructor?
Yes: the Dynamic Binding During Initialization idiom (AKA Calling Virtuals During Initialization).
To clarify, we're talking about this situation:
class Base {
public:
Base();
...
virtual void foo(int n) const; // often pure virtual
virtual double bar() const; // often pure virtual
// if you don't want outsiders calling these, make them protected
};
Base::Base()
{
... foo(42) ... bar() ...
// these will not use dynamic binding
// goal: simulate dynamic binding in those calls
}
class Derived : public Base {
public:
...
virtual void foo(int n) const;
virtual double bar() const;
};
This FAQ shows some ways to simulate dynamic binding as if the
calls made in Base's constructor dynamically bound to the this object's
derived class. The ways we'll show have tradeoffs, so choose the one that
best fits your needs, or make up another.
The first approach is a two-phase initialization. In Phase I, someone calls
the actual constructor; in Phase II, someone calls an "init" method on the
object. Dynamic binding on the this object works fine during Phase II, and
Phase II is conceptually part of construction, so we simply move some
code from the original Base::Base() into Base::init().
class Base {
public:
void init(); // may or may not be virtual
...
virtual void foo(int n) const; // often pure virtual
virtual double bar() const; // often pure virtual
};
void Base::init()
{
... foo(42) ... bar() ...
// most of this is copied from the original Base::Base()
}
class Derived : public Base {
public:
...
virtual void foo(int n) const;
virtual double bar() const;
};
The only remaining issues are determining where to call Phase I and
where to call Phase II. There are many variations on where these
calls can live; we will consider two.
The first variation is simplest initially, though the code that actually wants
to create objects requires a tiny bit of programmer self-discipline, which in
practice means you're doomed. Seriously, if there are only one or two places
that actually create objects of this hierarchy, the programmer self-discipline
is quite localized and shouldn't cause problems.
In this variation, the code that is creating the object explicitly executes
both phases. When executing Phase I, the code creating the object either
knows the object's exact class (e.g., new Derived() or perhaps a local
Derived object), or doesn't know the object's exact class (e.g.,
the virtual constructor idiom or some other
factory). The "doesn't know" case is strongly preferred when you want to make
it easy to plug-in new derived classes.
Note: Phase I often, but not always, allocates the object from the heap. When
it does, you should store the pointer in some sort of
managed pointer, such as a
std::auto_ptr, a
reference counted pointer, or some other object
whose destructor deletes the allocation.
This is the best way to prevent memory leaks when Phase II might
throw exceptions. The following example assumes Phase
I allocates the object from the heap.
#include <memory>
void joe_user()
{
std::auto_ptr<Base> p(/*...somehow create a Derived object via new...*/);
p->init();
...
}
The second variation is to combine the first two lines of the joe_user
function into some create function. That's almost always the right
thing to do when there are lots of joe_user-like functions. For
example, if you're using some kind of factory, such as a registry and
the virtual constructor idiom, you could move those
two lines into a static method called Base::create():
#include <memory>
class Base {
public:
...
typedef std::auto_ptr<Base> Ptr; // typedefs simplify the code
static Ptr create();
...
};
Base::Ptr Base::create()
{
Ptr p(/*...use a factory to create a Derived object via new...*/);
p->init();
return p;
}
This simplifies all the joe_user-like functions (a little), but more
importantly, it reduces the chance that any of them will create a Derived
object without also calling init() on it.
void joe_user()
{
Base::Ptr p = Base::create();
...
}
If you're sufficiently clever and motivated, you can even eliminate
the chance that someone could create a Derived object without also calling
init() on it. An important step in achieving that goal is to
make Derived's constructors, including its copy
constructor, protected or private..
The next approach does not rely on a two-phase initialization, instead using a
second hierarchy whose only job is to house methods foo() and
bar(). This approach doesn't always work, and in particular it
doesn't work in cases when foo() and bar() need to access the
instance data declared in Derived, but it is conceptually quite simple and
clean and is commonly used.
Let's call the base class of this second hierarchy Helper, and its
derived classes Helper1, Helper2, etc. The first step is to
move foo() and bar() into this second hierarchy:
class Helper {
public:
virtual void foo(int n) const = 0;
virtual double bar() const = 0;
};
class Helper1 : public Helper {
public:
virtual void foo(int n) const;
virtual double bar() const;
};
class Helper2 : public Helper {
public:
virtual void foo(int n) const;
virtual double bar() const;
};
Next, remove init() from Base (since we're no longer using the two-phase
approach), remove foo() and bar() from Base and Derived
(foo() and bar() are now in the Helper hierarchy), and
change the signature of Base's constructor so it takes a Helper by
reference:
class Base {
public:
Base(const Helper& h);
... // remove init() since not using two-phase this time
... // remove foo() and bar() since they're in Helper
};
class Derived : public Base {
public:
... // remove foo() and bar() since they're in Helper
};
We then define Base::Base(const Helper&) so it calls h.foo(42)
and h.bar() in exactly those places that init() used to call
this->foo(42) and this->bar():
Base::Base(const Helper& h)
{
... h.foo(42) ... h.bar() ...
// almost identical to the original Base::Base()
// but with h. in calls to h.foo() and h.bar()
}
Finally we change Derived's constructor to pass a (perhaps temporary) object
of an appropriate Helper derived class to Base's constructor (using
the init list syntax). For example, Derived would
pass an instance of Helper2 if it happened to contain the behaviors
that Derived wanted for methods foo() and bar():
Derived::Derived()
: Base(Helper2()) // ←the magic happens here
{
...
}
Note that Derived can pass values into the Helper derived class's
constructor, but it must not pass any data members that actually live
inside the this object. While we're at it, let's explicitly say that
Helper::foo() and Helper::bar() must not access data members
of the this object, particularly data members declared in Derived. (Think
about when those data members are initialized and you'll see why.)
Of course the choice of which Helper derived class could be made out
in the joe_user-like function, in which case it would be passed into
the Derived ctor and then up to the Base ctor:
Derived::Derived(const Helper& h)
: Base(h)
{
...
}
If the Helper objects don't need to hold any data, that is, if each is
merely a collection of its methods, then you can simply pass
static member functions instead. This
might be simpler since it entirely eliminates the Helper hierarchy.
class Base {
public:
typedef void (*FooFn)(int); // typedefs simplify
typedef double (*BarFn)(); // the rest of the code
Base(FooFn foo, BarFn bar);
...
};
Base::Base(FooFn foo, BarFn bar)
{
... foo(42) ... bar() ...
// almost identical to the original Base::Base()
// except calls are made via function pointers.
}
The Derived class is also easy to implement:
class Derived : public Base {
public:
Derived();
static void foo(int n); // the static is important!
static double bar(); // the static is important!
...
};
Derived::Derived()
: Base(foo, bar) // ←pass the function-ptrs into Base's ctor
{
...
}
As before, the functionality for foo() and/or bar() can be
passed in from the joe_user-like functions. In that case, Derived's
ctor just accepts them and passes them up into Base's ctor:
Derived::Derived(FooFn foo, BarFn bar)
: Base(foo, bar)
{
...
}
A final approach is to use templates to "pass" the functionality into the
derived classes. This is similar to the case where the joe_user-like
functions choose the initializer-function or the Helper derived class,
but instead of using function pointers or dynamic binding, it wires the code
into the classes via templates.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.5] I'm getting the same mess with destructors: calling a virtual on my this object from my base class's destructor ends up ignoring the override in the derived class; what's going on?
C++ is protecting you from yourself. What you are trying to do is very
dangerous, and if the compiler did what you wanted, you'd be in worse shape.
For rationale of why C++ needs to protect you from that danger, read FAQ
[23.3]. The situation during a destructor is
analogous to that during the constructor. In particular, within the
{body} of Base::~Base(), an object that was originally
of type Derived has already been demoted (devolved, if you will) to an
object of type Base. If you call a virtual function that has been
overridden in class Derived, the call will resolve to
Base::virt(), not to the override Derived::virt(). Same goes
for using typeid on the this object: the this object
really has been demoted to type Base; it is no longer an object of
type Derived.
Read FAQ [23.3] for more insight on this
matter.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.6] Should a derived class redefine ("override") a member function that is non-virtual in a base class?
It's legal, but it ain't moral.
Experienced C++ programmers will sometimes redefine a non-virtual function
for efficiency (e.g., if the derived class implementation can make better use
of the derived class's resources) or to get around the hiding
rule. However the client-visible effects must be identical,
since non-virtual functions are dispatched based on the static type of the
pointer/reference rather than the dynamic type of the pointed-to/referenced
object.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.7] What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?
It means you're going to die.
Here's the mess you're in: if Base declares a member function
f(double x), and Derived declares a member function f(char
c) (same name but different parameter types and/or constness), then the
Base f(double x) is "hidden" rather than "overloaded" or
"overridden" (even if the Base f(double x) is
virtual).
class Base {
public:
void f(double x); ← doesn't matter whether or not this is virtual
};
class Derived : public Base {
public:
void f(char c); ← doesn't matter whether or not this is virtual
};
int main()
{
Derived* d = new Derived();
Base* b = d;
b->f(65.3); ← okay: passes 65.3 to f(double x)
d->f(65.3); ← bizarre: converts 65.3 to a char ('A' if ASCII) and passes it to f(char c); does NOT call f(double x)!!
return 0;
}
Here's how you get out of the mess: Derived must have a using
declaration of the hidden member function. For example,
class Base {
public:
void f(double x);
};
class Derived : public Base {
public:
using Base::f; ← This un-hides Base::f(double x)
void f(char c);
};
If the using syntax isn't supported by your compiler, redefine the
hidden Base member function(s), even if they are
non-virtual. Normally this re-definition merely calls the hidden
Base member function using the :: syntax. E.g.,
class Derived : public Base {
public:
void f(double x) { Base::f(x); } ← The redefinition merely calls Base::f(double x)
void f(char c);
};
Note: the hiding problem also occurs if class Base declares a method
f(char).
Note: warnings are not part of the standard, so your compiler may or may not
give the above warning.
Note: nothing gets hidden when you have a base-pointer. Think about it: what
a derived class does or does not do is irrelevant when the compiler is dealing
with a base-pointer. The compiler might not even know that the particular
derived class exists. Even if it knows of the existence some particular
derived class, it cannot assume that a specific base-pointer necessarily
points at an object of that particular derived class. Hiding takes place when
you have a derived pointer, not when you have a base pointer.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.8] What does it mean that the "virtual table" is an unresolved external?
If you get a link error of the form "Error: Unresolved or undefined symbols
detected: virtual table for class Fred," you probably have an undefined
virtual member function in class Fred.
The compiler typically creates a magical data structure called the "virtual
table" for classes that have virtual functions (this is how it handles
dynamic binding). Normally you don't
have to know about it at all. But if you forget to define a virtual function
for class Fred, you will sometimes get this linker error.
Here's the nitty gritty: Many compilers put this magical "virtual table" in the
compilation unit that defines the first non-inline virtual function in the
class. Thus if the first non-inline virtual function in Fred is
wilma(), the compiler will put Fred's virtual table in the same compilation
unit where it sees Fred::wilma(). Unfortunately if you accidentally
forget to define Fred::wilma(), rather than getting a
Fred::wilma() is undefined, you may get a "Fred's virtual table is
undefined". Sad but true.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.9] How can I set up my class so it won't be inherited from?
This is known as making the class "final" or "a leaf." There are three ways
to do it: an easy technical approach, an even easier non-technical approach,
and a slightly trickier technical approach.
The (easy) technical approach is to make the class's constructors
private and to use the Named Constructor
Idiom to create the objects. No one can create objects of a derived
class since the base class's constructor will be inaccessible. The "named
constructors" themselves could return by pointer
if you want your objects allocated by new or they could
return by value if you want the objects created on the
stack.
The (even easier) non-technical approach is to put a big fat ugly
comment next to the class definition. The comment could say, for example,
// We'll fire you if you inherit from this class or even just
/*final*/ class Whatever {...};. Some programmers balk at this
because it is enforced by people rather than by technology, but don't knock it
on face value: it is quite effective in practice.
A slightly trickier technical approach is to exploit
virtual inheritance. Since
the most derived class's ctor needs to
directly call the virtual base class's ctor, the following guarantees
that no concrete class can inherit from class Fred:
class Fred;
class FredBase {
private:
friend class Fred;
FredBase() { }
};
class Fred : private virtual FredBase {
public:
...
};
Class Fred can access FredBase's ctor, since Fred is a
friend of FredBase, but no class derived from Fred can
access FredBase's ctor, and therefore no one can create a concrete
class derived from Fred.
If you are in extremely space-constrained environments (such as an embedded
system or a handheld with limited memory, etc.), you should be aware that the
above technique might add a word of memory to sizeof(Fred). That's
because most compilers implement virtual inheritance by adding a pointer in
objects of the derived class. This is compiler specific; your mileage may
vary.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[23.10] How can I set up my member function so it won't be overridden in a derived class?
This is known as making the method "final" or "a leaf." Here's an easy-to-use
solution to this that gives you 90+% of what you want: simply add a comment
next to the method and rely on code reviews or random maintenance activities
to find violators. The comment could say, for example, // We'll fire you
if you override this method or perhaps more likely, /*final*/ void
theMethod();.
The advantages to this technique are (a) it is extremely easy/fast/inexpensive
to use, and (b) it is quite effective in practice. In other words, you get
90+% of the benefit with almost no cost lots of bang per buck.
(I'm not aware of a "100% solution" to this problem so this may be the best
you can get. If you know of something better, please let me know,
cline@parashift.com. But please do
not email me objecting to this solution because it's low-tech or
because it doesn't "prevent" people from doing the wrong thing. Who cares
whether it's low-tech or high-tech as long as it's effective?!? And nothing
in C++ "prevents" people from doing the wrong thing. Using
pointer casts and pointer arithmetic, people can do
just about anything they want. C++ makes it easy to do the right thing, but
it doesn't prevent espionage.
Besides, the original question (see above) asked for something so people
won't do the wrong thing, not so they can't do the wrong
thing.)
In any case, this solution should give you most of the potential benefit at
almost no cost.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Jun 1, 2005