Why is the "virtuality" of methods implicitly propagated in C++? - c++

What is the reason for removing the ability to stop the propagation of methods virtuality?
Let me be clearer: In C++, whether you write "virtual void foo()" or "void foo()" in the derived class, it will be virtual as long as in the base class, foo is declared virtual.
This means that a call to foo() through a derived* pointer will result in a virtual table lookup (in case a derived2 function overrides foo), even if this behavior is not wanted by the programmer.
Let me give you an example (that looks pretty blatant to me) of how it would be useful to stop virtuality propagation:
template <class T>
class Iterator // Here is an iterator interface useful for defining iterators
{ // when implementation details need to be hidden
public:
virtual T& next() { ... }
...
};
template <class T>
class Vector
{
public:
class VectIterator : public Iterator<T>
{
public:
T& next() { ... }
...
};
...
};
In the example above, the Iterator base class can be used to achieve a form of "type erasure" in a much more clearer and Object-Oriented way. (See http://www.artima.com/cppsource/type_erasure.html for an example of type erasure.)
But still, in my example one can use a Vector::VectIterator object directly (which will be done in most cases) in order to access the real object without using the interface.
If virtuality was not propagated, calls to Vector::VectIterator::next() even from a pointer or reference would not be virtual and would be able to be inlined and to run efficiently, just as if the Iterator interface didn't exist.

C++11 added the contextual keyword final for this purpose.
class VectIterator : public Iterator<T>
{
public:
T& next() final { ... }
...
};
struct Nope : VecIterator {
T& next() { ... } // ill-formed
};

The simple snswer is : Don't mix concrete and abstract interfaces! The obvious approach in you example would be the use of a non-virtual function next() which delegates to a virtual function, e.g., do_next(). A derived class would override do_next() possibly delegating to a non-virtual function next(). Since the next() functions are likely inline there isn't any cost involved in the delegation.

In my opinion one of the good reasons for this propagation is the virtual destructors. In C++ when you have a base class with some virtual methods you should define the destructor virtual. This is because some code may have a pointer of base class which is actually pointing to the derived class and then tries to delete this pointer (see this question for more detail).
By defining the destructor in base class as vritual you can make sure all pointers of base class pointing to a derived class (in any level of inheritance) will delete properly.

I think the reason is that it would be really confusing to remove virtuality partway through an inheritance structure (I have an example of the complexity below).
However if your concern is the micro-optimization of removing a few virtual calls then I wouldn't worry. As long as you inline the virtual child method's code, AND your iterator is passed around by value and not reference, a good optimizing compiler will already be able to see the dynamic type at compile time and inline the whole thing for you in spite of it being a virtual method!
But for completeness, consider the following in a language where you can de-virtualize:
class A
{
public:
virtual void Foo() { }
};
class B : public A
{
public:
void Foo() { } // De-virtualize
};
class C: public B
{
public:
void Foo() { } // not virtual
};
void F1(B* obj)
{
obj->Foo();
static_cast<A*>(obj)->Foo();
}
C test_obj;
F1(test_obj); // Which two methods are called here?
You could make rules for exactly which methods would get called but the obvious choice will vary from person-to-person. It's far simpler to just propagate virtualness of a method.

Related

How do I specify a C++ virtual function that is guaranteed to be called by any overriding function? [duplicate]

One very common mistake with class hierarchies is to specify a method in a base class as being virtual, in order for all overrides in the inheritance chain to do some work, and forgetting to propagate the call on to base implementations.
Example scenario
class Container
{
public:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Nothing to do here
}
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Set some property of pObject and pass on.
Container::PrepareForInsertion(pObject);
}
};
class MoreSpecializedContainer : public SpecializedContainer
{
protected:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Oops, forgot to propagate!
}
};
My question is: is there a good way/pattern to ensure that the base implementation always gets called at the end of the call chain?
I know of two methods to do this.
Method 1
You can use a member variable as a flag, set it to the correct value in the base implementation of the virtual method, and check its value after the call. This requires to use a public non-virtual method as interface for the clients, and making the virtual method protected (which is actually a good thing to do), but it requires the use of a member variable specifically for this purpose (which needs to be mutable if the virtual method must be const).
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
m_callChainCorrect = false;
PrepareForInsertionImpl(pObject);
assert(m_callChainCorrect);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
m_callChainCorrect = true;
}
private:
bool m_callChainCorrect;
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// Do something and pass on
Container::PrepareForInsertionImpl(pObject);
}
};
Method 2
The other way to do it is to replace the member variable with an opaque "cookie" parameter and do the same thing:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
bool callChainCorrect = false;
PrepareForInsertionImpl(pObject, &callChainCorrect);
assert(callChainCorrect);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject, void* pCookie)
{
*reinrepret_cast<bool*>(pCookie) = true;
}
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject, void* pCookie)
{
// Do something and pass on
Container::PrepareForInsertionImpl(pObject, pCookie);
}
};
This approach is inferior to the first one in my opinion, but it does avoid the use of a dedicated member variable.
What other possibilities are there?
You've come up with some clever ways to do this, at (as you acknowledge) the cost of bloating the class and adding code that addresses not the object's responsibilities but programmer deficiences.
The real answer is not to do this at runtime. This is a programmer error, not a runtime error.
Do it at compile time: use a language construct if the language supports it, or use a Pattern the enforces it (e.g,, Template Method), or make your compilation dependent on tests passing, and set up tests to enforce it.
Or, if failing to propagate causes the derived class to fail, let it fail, with an exception message that informs the author of the derived class that he failed to use the base class correctly.
What you are looking for is simply the Non-Virtual Interface pattern.
It's similar to what you are doing here, but the base class implementation is guaranteed to be called because it's the only implementation that can be called. It eliminates the clutter that your examples above require. And the call through the base class is automatic, so derived versions don't need to make an explicit call.
Google "Non-Virtual Interface" for details.
Edit: After looking up "Template Method Pattern", I see that it's another name for Non-Virtual Interface. I've never heard it referred to by the name before (I'm not exactly a card-carrying member of the GoF fan club). Personally, I prefer the name Non-Virtual Interface because the name itself actually describes what the pattern is.
Edit Again: Here's the NVI way of doing this:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
PrepareForInsertionImpl(pObject);
// If you put some base class implementation code here, then you get
// the same effect you'd get if the derived class called the base class
// implementation when it's finished.
//
// You can also add implementation code in this function before the call
// to PrepareForInsertionImpl, if you want.
}
private:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject) = 0;
};
class SpecializedContainer : public Container
{
private:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// Do something and return to the base class implementation.
}
};
When there's only one level of inheritance you can use the template method pattern where the public interface is non-virtual and calls a virtual implementation function. Then the base's logic goes in the public function which is assured to be called.
If you have more than one level of inheritance and want each class to call its base class then you can still use the template method pattern, but with a twist, make the return value of the virtual function only constructable by base so derived will be forced to call the base implementation in order to return a value (enforced at compile time).
This doesn't enforce that each class calls its direct base class, it may skip a level (I can't think of a good way to enforce that) but it does force the programmer to make a conscious decision, in other words it works against inattentiveness not malice.
class base {
protected:
class remember_to_call_base {
friend base;
remember_to_call_base() {}
};
virtual remember_to_call_base do_foo() {
/* do common stuff */
return remember_to_call_base();
}
remember_to_call_base base_impl_not_needed() {
// allow opting out from calling base::do_foo (optional)
return remember_to_call_base();
}
public:
void foo() {
do_foo();
}
};
class derived : public base {
remember_to_call_base do_foo() {
/* do specific stuff */
return base::do_foo();
}
};
If you need the public (non virtual) function to return a value the inner virtual one should return std::pair<return-type, remember_to_call_base>.
Things to note:
remember_to_call_base has an explicit constructor declared private so only its friend (in this case base) can create a new instance of this class.
remember_to_call_base doesn't have an explicitly defined copy constructor so the compiler will create one with public accessibility which allows returning it by value from the base implementation.
remember_to_call_base is declared in the protected section of base, if it was in the private section derived won't be able to reference it at all.
A completely different approach would be to register functors. Derived classes would register some function (or member function) with the base class while in the derived class constructor. When the actual function is called by the client it is a base class function which then iterates through the registered functions. This scales to many levels of inheritance, each derived class only has to be concerned with its own function.
Look at the template method pattern. (The basic idea is that you don't have to call the base class method anymore.)
One way out is to not use virtual methods at all, but instead to allow the user to register callbacks, and call those before doing the work of prepareForInsertion. This way it becomes impossible to make that mistake since it is the base class that makes sure that both the callbacks and the normal processing happen. You can end up with a lot of callbacks if you want this behaviour for a lot of functions. If you really do use that pattern so much, you might want to look into tools like AspectJ (or whatever the C# equivalent is) that can automate this sort of thing.
If you found out you can hide virtual function and make interface non-virtual, try instead of checking if other users did call your function just call it by yourself. If your base code should be called at the end, it would look like this:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
PrepareForInsertionImpl(pObject);
doBasePreparing(pObject);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// nothing to do
}
private:
void doBasePreparing(ObjectToInsert* pObject)
{
// put here your code from Container::PrepareForInsertionImpl
}
};

Pure virtual function in class implementation [duplicate]

My basic understanding is that there is no implementation for a pure virtual function, however, I was told there might be implementation for pure virtual function.
class A {
public:
virtual void f() = 0;
};
void A::f() {
cout<<"Test"<<endl;
}
Is code above OK?
What's the purpose to make it a pure virtual function with an implementation?
A pure virtual function must be implemented in a derived type that will be directly instantiated, however the base type can still define an implementation. A derived class can explicitly call the base class implementation (if access permissions allow it) by using a fully-scoped name (by calling A::f() in your example - if A::f() were public or protected). Something like:
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
The use case I can think of off the top of my head is when there's a more-or-less reasonable default behavior, but the class designer wants that sort-of-default behavior be invoked only explicitly. It can also be the case what you want derived classes to always perform their own work but also be able to call a common set of functionality.
Note that even though it's permitted by the language, it's not something that I see commonly used (and the fact that it can be done seems to surprise most C++ programmers, even experienced ones).
To be clear, you are misunderstanding what = 0; after a virtual function means.
= 0 means derived classes must provide an implementation, not that the base class can not provide an implementation.
In practice, when you mark a virtual function as pure (=0), there is very little point in providing a definition, because it will never be called unless someone explicitly does so via Base::Function(...) or if the Base class constructor calls the virtual function in question.
The advantage of it is that it forces derived types to still override the method but also provides a default or additive implementation.
If you have code that should be executed by the deriving class, but you don't want it to be executed directly -- and you want to force it to be overriden.
Your code is correct, although all in all this isn't an often used feature, and usually only seen when trying to define a pure virtual destructor -- in that case you must provide an implementation. The funny thing is that once you derive from that class you don't need to override the destructor.
Hence the one sensible usage of pure virtual functions is specifying a pure virtual destructor as a "non-final" keyword.
The following code is surprisingly correct:
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived : public Base {};
int main() {
// Base b; -- compile error
Derived d;
}
You'd have to give a body to a pure virtual destructor, for example :)
Read: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/
(Link broken, use archive)
Pure virtual functions with or without a body simply mean that the derived types must provide their own implementation.
Pure virtual function bodies in the base class are useful if your derived classes wants to call your base class implementation.
Yes this is correct. In your example, classes that derive from A inherit both the interface f() and a default implementation. But you force derived classes to implement the method f() (even if it is only to call the default implementation provided by A).
Scott Meyers discusses this in Effective C++ (2nd Edition) Item #36 Differentiate between inheritance of interface and inheritance of implementation. The item number may have changed in the latest edition.
The 'virtual void foo() =0;' syntax does not mean you can't implement foo() in current class, you can. It also does not mean you must implement it in derived classes.
Before you slap me, let's observe the Diamond Problem:
(Implicit code, mind you).
class A
{
public:
virtual void foo()=0;
virtual void bar();
}
class B : public virtual A
{
public:
void foo() { bar(); }
}
class C : public virtual A
{
public:
void bar();
}
class D : public B, public C
{}
int main(int argc, const char* argv[])
{
A* obj = new D();
**obj->foo();**
return 0;
}
Now, the obj->foo() invocation will result in B::foo() and then C::bar().
You see... pure virtual methods do not have to be implemented in derived classes (foo() has no implementation in class C - compiler will compile)
In C++ there are a lot of loopholes.
Hope I could help :-)
If I ask you what's the sound of an animal, the correct response is to ask which animal, that's exactly the purpose of pure virtual functions, or abstract function is when you cannot provide an implementation to your function in the base class (Animal) but each animal has its own sound.
class Animal
{
public:
virtual void sound() = 0;
}
class Dog : public Animal
{
public:
void sound()
{
std::cout << "Meo Meo";
}
}
One important use-case of having a pure virtual method with an implementation body, is when you want to have an abstract class, but you do not have any proper methods in the class to make it pure virtual. In this case, you can make the destructor of the class pure virtual and put your desired implementation (even an empty body) for that. As an example:
class Foo
{
virtual ~Foo() = 0;
void bar1() {}
void bar2(int x) {}
// other methods
};
Foo::~Foo()
{
}
This technique, makes the Foo class abstract and as a result impossible to instantiate the class directly. At the same time you have not added an additional pure virtual method to make the Foo class abstract.

C++ : Automatically run function when derived class is constructed

So I recently accidentally called some virtual functions from the constructor of a base class, i.e. Calling virtual functions inside constructors.
I realise that I should not do this because overrides of the virtual function will not be called, but how can I achieve some similar functionality? My use-case is that I want a particular function to be run whenever an object is constructed, and I don't want people who write derived classes to have to worry about what this is doing (because of course they could call this thing in their derived class constructor). But, the function that needs to be called in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
But because a virtual function gets called, I can't just stick this function in the constructor of the base class and have it get run automatically that way. So I seem to be stuck.
Is there some other way to achieve what I want?
edit: I happen to be using the CRTP to access other methods in the derived class from the base class, can I perhaps use that instead of virtual functions in the constructor? Or is much the same issue present then? I guess perhaps it can work if the function being called is static?
edit2: Also just found this similar question: Call virtual method immediately after construction
If really needed, and you have access to the factory.
You may do something like:
template <typename Derived, typename ... Args>
std::unique_ptr<Derived> Make(Args&&... args)
{
auto derived = std::make_unique<Derived>(std::forward<Args>(args));
derived->init(); // virtual call
return derived;
}
There is no simple way to do this. One option would be to use so-called virtual constructor idiom, hide all constructors of the base class, and instead expose static 'create' - which will dynamically create an object, call your virtual override on it and return (smart)pointer.
This is ugly, and what is more important, constrains you to dynamically created objects, which is not the best thing.
However, the best solution is to use as little of OOP as possible. C++ strength (contrary to popular belief) is in it's non-OOP specific traits. Think about it - the only family of polymorphic classess inside standard library are streams, which everybody hate (because they are polymorphic!)
I want a particular function to be run whenever an object is constructed, [... it] in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
This can be easily done if you're willing to live with two restrictions:
the constructors in the entire class hierarchy must be non-public, and thus
a factory template class must be used to construct the derived class.
Here, the "particular function" is Base::check, and the virtual function is Base::method.
First, we establish the base class. It has to fulfill only two requirements:
It must befriend MakeBase, its checker class. I assume that you want the Base::check method to be private and only usable by the factory. If it's public, you won't need MakeBase, of course.
The constructor must be protected.
https://github.com/KubaO/stackoverflown/tree/master/questions/imbue-constructor-35658459
#include <iostream>
#include <utility>
#include <type_traits>
using namespace std;
class Base {
friend class MakeBase;
void check() {
cout << "check()" << endl;
method();
}
protected:
Base() { cout << "Base()" << endl; }
public:
virtual ~Base() {}
virtual void method() {}
};
The templated CRTP factory derives from a base class that's friends with Base and thus has access to the private checker method; it also has access to the protected constructors in order to construct any of the derived classes.
class MakeBase {
protected:
static void check(Base * b) { b->check(); }
};
The factory class can issue a readable compile-time error message if you inadvertently use it on a class not derived from Base:
template <class C> class Make : public C, MakeBase {
public:
template <typename... Args> Make(Args&&... args) : C(std::forward<Args>(args)...) {
static_assert(std::is_base_of<Base, C>::value,
"Make requires a class derived from Base");
check(this);
}
};
The derived classes must have a protected constructor:
class Derived : public Base {
int a;
protected:
Derived(int a) : a(a) { cout << "Derived() " << endl; }
void method() override { cout << ">" << a << "<" << endl; }
};
int main()
{
Make<Derived> d(3);
}
Output:
Base()
Derived()
check()
>3<
If you take a look at how others solved this problem, you will notice that they simply transferred the responsibility of calling the initialization function to client. Take MFC’s CWnd, for instance: you have the constructor and you have Create, a virtual function that you must call to have a proper CWnd instantiation: “these are my rules: construct, then initialize; obey, or you’ll get in trouble”.
Yes, it is error prone, but it is better than the alternative: “It has been suggested that this rule is an implementation artifact. It is not so. In fact, it would be noticeably easier to implement the unsafe rule of calling virtual functions from constructors exactly as from other functions. However, that would imply that no virtual function could be written to rely on invariants established by base classes. That would be a terrible mess.” - Stroustrup. What he meant, I reckon, is that it would be easier to set the virtual table pointer to point to the VT of derived class instead of keep changing it to the VT of current class as your constructor call goes from base down.
I realise that I should not do this because overrides of the virtual function will not be called,...
Assuming that the call to a virtual function would work the way you want, you shouldn't do this because of the invariants.
class B // written by you
{
public:
B() { f(); }
virtual void f() {}
};
class D : public B // written by client
{
int* p;
public:
D() : p( new int ) {}
void f() override { *p = 10; } // relies on correct initialization of p
};
int main()
{
D d;
return 0;
}
What if it would be possible to call D::f from B via VT of D? You will use an uninitialized pointer, which will most likely result in a crash.
...but how can I achieve some similar functionality?
If you are willing to break the rules, I guess that it might be possible to get the address of desired virtual table and call the virtual function from constructor.
Seems you want this, or need more details.
class B
{
void templateMethod()
{
foo();
bar();
}
virtual void foo() = 0;
virtual void bar() = 0;
};
class D : public B
{
public:
D()
{
templateMethod();
}
virtual void foo()
{
cout << "D::foo()";
}
virtual void bar()
{
cout << "D::bar()";
}
};

CRTP Dispatch in C++11

Say I have the following code:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl(); //A
(*static_cast<Derived*>(this)).foo_impl(); //B
}
};
class Derived : public Base<Derived> {
private:
void foo_impl() {
bar();
}
};
A few questions:
Will line A generate a virtual function call? Although the majority of what I can find on the internet recommends doing things this way, to me I don't see how the compiler can do static dispatch considering that a pointer to Derived could still actually point to an object of type Derived2 where Derived2 : public Derived.
Does line B fix the issue I brought up in my previous point (if applicable)? It seems like it would, considering that now the call is not on a pointer any more and thus using *. would avoid a virtual function call. But if the compiler treats the dereferenced cast as a reference type, it could still generate a virtual function call... in that case, what is the workaround?
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
Will line A generate a virtual function call?
Yes. foo_impl() is virtual and Derived overrides it. Even though foo_impl() in Derived is not explicitly tagged as virtual, it is in the base class, and this is enough to make it a virtual function.
Does line B fix the issue I brought up in my previous point (if applicable)?
No. It does not matter if the call is on a pointer or on a reference: the compiler still won't know whether you are invoking the function foo_impl() on an instance of a class that derives from Derived, or on a direct instance of Derived. Thus, the call is performed through a vtable.
To see what I mean:
#include <iostream>
using namespace std;
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl();
(*static_cast<Derived*>(this)).foo_impl();
}
};
class Derived : public Base<Derived> {
public:
void foo_impl() {
cout << "Derived::foo_impl()" << endl;
}
};
class MoreDerived : public Derived {
public:
void foo_impl() {
cout << "MoreDerived::foo_impl()" << endl;
}
};
int main()
{
MoreDerived d;
d.foo(); // Will output "MoreDerived::foo_impl()" twice
}
Finally:
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
In theory, yes. The final keyword would make it impossible to override that function in subclasses of Derived. Thus, when performing a function call to foo_impl() through a pointer to Derived, the compiler could resolve the call statically. However, to the best of my knowledge, compilers are not required to do so by the C++ Standard.
CONCLUSION:
In any case, I believe what you actually want to do is not to declare the foo_impl() function at all in the base class. This is normally the case when you use the CRTP. Additionally, you will have to declare class Base<Derived> a friend of Derived if you want it to access Derived's private function foo_impl(). Otherwise, you can make foo_impl() public.
The common idiom for the CRTP does not involve declaring the pure virtual functions in the base. As you mention in one of the comments, that means that the compiler will not enforce the definition of the member in the derived type (other than through use, if there is any use of foo in the base, that requires the presence of foo_impl in the derived type).
While I would stick to the common idiom and not define the pure virtual function in the base, but, if you really feel you need to do it, you can disable dynamic dispatch by adding extra qualification:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->Derived::foo_impl();
// ^^^^^^^^^
}
};
The use of the extra qualification Derived:: disables dynamic dispatch, and that call will be statically resolved to Derived::foo_impl. Note that this comes will all of the usual caveats: you have a class with a virtual function and paying the cost of the virtual pointer per object, but you cannot override that virtual function in a most derived type, as the use in the CRTP base is blocking dynamic dispatch...
The extra verbiage in lines A and B have absolutely no effect on
the generated code. I don't know who recommends this (I've never seen
it), but in practice, the only time it might have an effect is
if the function isn't virtual. Just write foo_impl(), and be
done with it.
There is a means of avoiding the virtual function call if the
compiler knows the derived type. I've seen it used for
vector-like classes (where there are different implementations,
e.g. normal, sparse, etc. of the vector):
template <typename T>
class Base
{
private:
virtual T& getValue( int index ) = 0;
public:
T& operator[]( int index ) { return getValue( index ); }
};
template <typename T>
class Derived : public Base<T>
{
private:
virtual T& getValue( int index )
{
return operator[]( index );
}
public:
T& operator[]( index )
{
// find element and return it.
}
};
The idea here is that you normally only work through references
to the base class, but if performance becomes an issue, because
you're using [] in a tight loop, you can dynamic_cast to the
derived class before the loop, and use [] on the derived
class.

How to ensure that virtual method calls get propagated all the way to the base class?

One very common mistake with class hierarchies is to specify a method in a base class as being virtual, in order for all overrides in the inheritance chain to do some work, and forgetting to propagate the call on to base implementations.
Example scenario
class Container
{
public:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Nothing to do here
}
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Set some property of pObject and pass on.
Container::PrepareForInsertion(pObject);
}
};
class MoreSpecializedContainer : public SpecializedContainer
{
protected:
virtual void PrepareForInsertion(ObjectToInsert* pObject)
{
// Oops, forgot to propagate!
}
};
My question is: is there a good way/pattern to ensure that the base implementation always gets called at the end of the call chain?
I know of two methods to do this.
Method 1
You can use a member variable as a flag, set it to the correct value in the base implementation of the virtual method, and check its value after the call. This requires to use a public non-virtual method as interface for the clients, and making the virtual method protected (which is actually a good thing to do), but it requires the use of a member variable specifically for this purpose (which needs to be mutable if the virtual method must be const).
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
m_callChainCorrect = false;
PrepareForInsertionImpl(pObject);
assert(m_callChainCorrect);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
m_callChainCorrect = true;
}
private:
bool m_callChainCorrect;
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// Do something and pass on
Container::PrepareForInsertionImpl(pObject);
}
};
Method 2
The other way to do it is to replace the member variable with an opaque "cookie" parameter and do the same thing:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
bool callChainCorrect = false;
PrepareForInsertionImpl(pObject, &callChainCorrect);
assert(callChainCorrect);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject, void* pCookie)
{
*reinrepret_cast<bool*>(pCookie) = true;
}
};
class SpecializedContainer : public Container
{
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject, void* pCookie)
{
// Do something and pass on
Container::PrepareForInsertionImpl(pObject, pCookie);
}
};
This approach is inferior to the first one in my opinion, but it does avoid the use of a dedicated member variable.
What other possibilities are there?
You've come up with some clever ways to do this, at (as you acknowledge) the cost of bloating the class and adding code that addresses not the object's responsibilities but programmer deficiences.
The real answer is not to do this at runtime. This is a programmer error, not a runtime error.
Do it at compile time: use a language construct if the language supports it, or use a Pattern the enforces it (e.g,, Template Method), or make your compilation dependent on tests passing, and set up tests to enforce it.
Or, if failing to propagate causes the derived class to fail, let it fail, with an exception message that informs the author of the derived class that he failed to use the base class correctly.
What you are looking for is simply the Non-Virtual Interface pattern.
It's similar to what you are doing here, but the base class implementation is guaranteed to be called because it's the only implementation that can be called. It eliminates the clutter that your examples above require. And the call through the base class is automatic, so derived versions don't need to make an explicit call.
Google "Non-Virtual Interface" for details.
Edit: After looking up "Template Method Pattern", I see that it's another name for Non-Virtual Interface. I've never heard it referred to by the name before (I'm not exactly a card-carrying member of the GoF fan club). Personally, I prefer the name Non-Virtual Interface because the name itself actually describes what the pattern is.
Edit Again: Here's the NVI way of doing this:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
PrepareForInsertionImpl(pObject);
// If you put some base class implementation code here, then you get
// the same effect you'd get if the derived class called the base class
// implementation when it's finished.
//
// You can also add implementation code in this function before the call
// to PrepareForInsertionImpl, if you want.
}
private:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject) = 0;
};
class SpecializedContainer : public Container
{
private:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// Do something and return to the base class implementation.
}
};
When there's only one level of inheritance you can use the template method pattern where the public interface is non-virtual and calls a virtual implementation function. Then the base's logic goes in the public function which is assured to be called.
If you have more than one level of inheritance and want each class to call its base class then you can still use the template method pattern, but with a twist, make the return value of the virtual function only constructable by base so derived will be forced to call the base implementation in order to return a value (enforced at compile time).
This doesn't enforce that each class calls its direct base class, it may skip a level (I can't think of a good way to enforce that) but it does force the programmer to make a conscious decision, in other words it works against inattentiveness not malice.
class base {
protected:
class remember_to_call_base {
friend base;
remember_to_call_base() {}
};
virtual remember_to_call_base do_foo() {
/* do common stuff */
return remember_to_call_base();
}
remember_to_call_base base_impl_not_needed() {
// allow opting out from calling base::do_foo (optional)
return remember_to_call_base();
}
public:
void foo() {
do_foo();
}
};
class derived : public base {
remember_to_call_base do_foo() {
/* do specific stuff */
return base::do_foo();
}
};
If you need the public (non virtual) function to return a value the inner virtual one should return std::pair<return-type, remember_to_call_base>.
Things to note:
remember_to_call_base has an explicit constructor declared private so only its friend (in this case base) can create a new instance of this class.
remember_to_call_base doesn't have an explicitly defined copy constructor so the compiler will create one with public accessibility which allows returning it by value from the base implementation.
remember_to_call_base is declared in the protected section of base, if it was in the private section derived won't be able to reference it at all.
A completely different approach would be to register functors. Derived classes would register some function (or member function) with the base class while in the derived class constructor. When the actual function is called by the client it is a base class function which then iterates through the registered functions. This scales to many levels of inheritance, each derived class only has to be concerned with its own function.
Look at the template method pattern. (The basic idea is that you don't have to call the base class method anymore.)
One way out is to not use virtual methods at all, but instead to allow the user to register callbacks, and call those before doing the work of prepareForInsertion. This way it becomes impossible to make that mistake since it is the base class that makes sure that both the callbacks and the normal processing happen. You can end up with a lot of callbacks if you want this behaviour for a lot of functions. If you really do use that pattern so much, you might want to look into tools like AspectJ (or whatever the C# equivalent is) that can automate this sort of thing.
If you found out you can hide virtual function and make interface non-virtual, try instead of checking if other users did call your function just call it by yourself. If your base code should be called at the end, it would look like this:
class Container
{
public:
void PrepareForInsertion(ObjectToInsert* pObject)
{
PrepareForInsertionImpl(pObject);
doBasePreparing(pObject);
}
protected:
virtual void PrepareForInsertionImpl(ObjectToInsert* pObject)
{
// nothing to do
}
private:
void doBasePreparing(ObjectToInsert* pObject)
{
// put here your code from Container::PrepareForInsertionImpl
}
};