As we all know, some languages have the notion of interfaces. This is Java:
public interface Testable {
void test();
}
How can I achieve this in C++ (or C++11) in most compact way and with little code noise? I'd appreciate a solution that wouldn't need a separate definition (let the header be sufficient). This is a very simple approach that even I find buggy ;-)
class Testable {
public:
virtual void test() = 0;
protected:
Testable();
Testable(const Testable& that);
Testable& operator= (const Testable& that);
virtual ~Testable();
}
This is only the beginning.. and already longer that I'd want. How to improve it? Perhaps there is a base class somewhere in the std namespace made just for this?
For dynamic (runtime) polymorphism, I would recommend using the Non-Virtual-Interface (NVI) idiom. This pattern keeps the interface non-virtual and public, the destructor virtual and public, and the implementation pure virtual and private
class DynamicInterface
{
public:
// non-virtual interface
void fun() { do_fun(); } // equivalent to "this->do_fun()"
// enable deletion of a Derived* through a Base*
virtual ~DynamicInterface() = default;
private:
// pure virtual implementation
virtual void do_fun() = 0;
};
class DynamicImplementation
:
public DynamicInterface
{
private:
virtual void do_fun() { /* implementation here */ }
};
The nice thing about dynamic polymorphism is that you can -at runtime- pass any derived class where a pointer or reference to the interface base class is expected. The runtime system will automatically downcast the this pointer from its static base type to its dynamic derived type and call the corresponding implementation (typically happens through tables with pointers to virtual functions).
For static (compile-time polymorphism), I would recommend using the Curiously Recurring Template Pattern (CRTP). This is considerably more involved because the automatic down-casting from base to derived of dynamic polymporphism has to be done with static_cast. This static casting can be defined in a helper class that each static interface derives from
template<typename Derived>
class enable_down_cast
{
private:
typedef enable_down_cast Base;
public:
Derived const* self() const
{
// casting "down" the inheritance hierarchy
return static_cast<Derived const*>(this);
}
Derived* self()
{
return static_cast<Derived*>(this);
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_down_cast() = default; // C++11 only, use ~enable_down_cast() {} in C++98
};
Then you define a static interface like this:
template<typename Impl>
class StaticInterface
:
// enable static polymorphism
public enable_down_cast< Impl >
{
private:
// dependent name now in scope
using enable_down_cast< Impl >::self;
public:
// interface
void fun() { self()->do_fun(); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~StaticInterface() = default; // C++11 only, use ~IFooInterface() {} in C++98/03
};
and finally you make an implementation that derives from the interface with itself as parameter
class StaticImplementation
:
public StaticInterface< StaticImplementation >
{
private:
// implementation
friend class StaticInterface< StaticImplementation > ;
void do_fun() { /* your implementation here */ }
};
This still allows you to have multiple implementations of the same interface, but you need to know at compile-time which implementation you are calling.
So when to use which form? Both forms will let you re-use a common interface and inject pre/post condition testing inside the interface class. The advantage of dynamic polymorphism is that you have runtime flexibility, but you pay for that in virtual function calls (typically a call through a function pointer, with little opportunity for inlining). Static polymporhism is the mirror of that: no virtual function call overhead, but the disadvantage is that you need more boilerplate code and you need to know what you are calling at compile-time. Basically an efficiency/flexiblity tradeoff.
NOTE: for compile-time polymporhism, you can also use template parameters. The difference between static interface through the CRTP idiom and ordinary template parameters is that CRTP-type interface are explicit (based on member functions), and template interface are implicit (based on valid expressions)
What about:
class Testable
{
public:
virtual ~Testable() { }
virtual void test() = 0;
}
In C++ this makes no implications about copyability of child classes. All this says is that the child must implement test (which is exactly what you want for an interface). You can't instantiate this class so you don't have to worry about any implicit constructors as they can't ever be called directly as the parent interface type.
If you wish to enforce that child classes implement a destructor you can make that pure as well (but you still have to implement it in the interface).
Also note that if you don't need polymorphic destruction you can choose to make your destructor protected non-virtual instead.
According to Scott Meyers (Effective Modern C++): When declaring interface (or polymorphic base class) you need virtual destructor, for proper results of operations like delete or typeid on a derived class object accessed through a base class pointer or reference.
virtual ~Testable() = default;
However, a user-declared destructor suppresses generation of the
move operations, so to support move operations you need to add:
Testable(Testable&&) = default;
Testable& operator=(Testable&&) = default;
Declaring the move operations disables copy operations and you need also:
Testable(const Testable&) = default;
Testable& operator=(const Testable&) = default;
And the final result is:
class Testable
{
public:
virtual ~Testable() = default; // make dtor virtual
Testable(Testable&&) = default; // support moving
Testable& operator=(Testable&&) = default;
Testable(const Testable&) = default; // support copying
Testable& operator=(const Testable&) = default;
virtual void test() = 0;
};
Another interesting article here: The Rule of Zero in C++
By replacing the word class with struct, all of the methods will be public by default and you can save a line.
There's no need to make the constructor protected, since you can't instantiate a class with pure virtual methods anyway. This goes for the copy constructor as well. The compiler-generated default constructor will be empty since you don't have any data members, and is completely sufficient for your derived classes.
You're right to be concerned about the = operator since the compiler-generated one will certainly do the wrong thing. In practice nobody ever worries about it because copying one interface object to another never makes sense; it's not a mistake that happens commonly.
Destructors for an inheritable class should always be either public and virtual, or protected and non-virtual. I prefer public and virtual in this case.
The final result is only one line longer than the Java equivalent:
struct Testable {
virtual void test() = 0;
virtual ~Testable();
};
Keep in mind that the "rule of three" is unnecessary if you aren't managing pointers, handles, and/or all the data-members of the class have their own destructors that will manage any clean-up. Also in the case of a virtual base class, because the base class can never be directly instantiated, it's not necessary to declare a constructor if all you're wanting to-do is define an interface that has no data members ... the compiler defaults are just fine. The only item you would need to keep is the virtual destructor if you are planning on calling delete on a pointer of the interface type. So in reality your interface can be as simple as:
class Testable
{
public:
virtual void test() = 0;
virtual ~Testable();
}
Related
I am trying to create an abstract class template (InstanceTracker) that classes can inherit from if they need functionality to perform operations on all of their instances. The class holds a static vector of pointers to 'T', and every time an InstanceTracker constructor is run, I push back a new pointer to the vector. I do this through a purely virtual getDerivedPtr() method that returns 'T*', that every class that derives from InstanceTracker has to implement with return this;. You can probably already see what is wrong what this though. You can never call a purely virtual function from a base constructor - since it doesn't exist yet. How can I find a way around this problem for my InstanceTracker class? Here's the code for the class:
#pragma once
#include <vector>
template <typename T>
class InstanceTracker
{
public:
InstanceTracker() noexcept
{
allInstances_.push_back(getDerivedPtr());
}
InstanceTracker(const InstanceTracker& source) noexcept
: InstanceTracker()
{
}
InstanceTracker(const InstanceTracker&& source) noexcept
: InstanceTracker()
{
}
virtual ~InstanceTracker() noexcept
{
auto it = std::find(allInstances_.begin(), allInstances_.end(), this);
int index = it - allInstances_.begin();
allInstances_.erase(allInstances_.begin() + index);
}
virtual T* getDerivedPtr() = 0;
protected:
static std::vector<T*> allInstances_;
};
If you want to try to run the code and see why it doesn't work at the moment, here's a simple class that inherits from InstanceTracker:
class Derived1 : public InstanceTracker
{
public:
Derived1* getDerivedPtr() override
{
return this;
}
};
You'd probably be better off using composition rather than inheritance, but I'll assume you have have a good reason to prefer inheritance here.
The difficulty is that, when a base class constructor is run, the this pointer is a pointer to an instance of the base class only. The derived instance doesn't even exit yet. (Likewise, on destruction, the derived portion of the object has already been uninitialized). So if you call a virtual method, you'll get the base class implementation rather than the derived class's implementation. In your case, the base class implementation doesn't even exist, so you're stuck.
You can probably get away with casting the base class's this pointer to a pointer to the derived class, but that's not guaranteed to work and probably involves undefined behavior.
One way to solve this is to store pointers to the base type (InstanceTracker *) rather the pointers to the derived type. Then your getDerivedPtr method doesn't need to be virtual, and it can do the cast when it's safe.
template <typename T>
class InstanceTracker {
public:
InstanceTracker() noexcept {
allInstances_.push_back(this);
}
// other constructors elided for space
virtual ~InstanceTracker() noexcept {
std::erase(
std::remove(allInstances_.begin(), allInstances_.end(),
this),
allInstances.end());
}
T* getDerivedPtr() {
return static_cast<T*>(this); // downcast
}
protected:
// allInstances_ stores base class pointers
static std::vector<InstanceTracker*> allInstances_;
};
Notes:
If you use RTTI, run-time type identification, you can use dynamic_cast instead of static_cast. You should not use a reinterpret_cast because the compiler might need to adjust the base pointer as part of the cast.
You're likely to run into problems if you create an instance of a derived type as const.
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
}
};
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.
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.
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
}
};