0

Possible Duplicate:
pure virtual function with implementation

I have a base class which has a function called time().
My idea is to have a pure virtual function which all the classes that inherits from it must implement.

However I also want to add the default behavior; Whoever calls time() function needs to print "hello".
Is that possible?

Community
  • 1
  • 1
Gilad
  • 6,437
  • 14
  • 61
  • 119

2 Answers2

3

The easiest way to achieve something like this would be to have something like the following:

  class base {
       virtual void time_impl()=0;
  public:
       void time() {
             //Default behaviour
             std::cout << "Hello\n";
             //Call overridden behaviour
             time_impl();
       }
  };

  class child : public base {
       void time_impl() override {
            //Functionality
       }
  };

This way, when any child's time function is called, it calls the base classes time function, which does the default behaviour, and then make the virtual call to the overridden behaviour.

EDIT:

As Als says in the comments, this is called the Template method pattern which you can read about here:

http://en.wikipedia.org/wiki/Template_method_pattern

Althought for C++ that is a rather confusing name (as templates are something else, and "methods" don't mean anything in C++ (rather member function).

EDIT:

Someone commented about the use of override, this is a C++11 feature, if you have it USE IT, it will save many headaches in the long run:

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

And also, the _impl function should be private, UNLESS you want the user to be to bypass the default behaviour, but I would argue that's a poor design in most use-cases.

Working test case

http://ideone.com/eZBpyX

111111
  • 15,686
  • 6
  • 47
  • 62
  • 1
    You might as well add, this is the famous Template method design pattern. – Alok Save Nov 25 '12 at 14:12
  • +1 for C++11 - I forgot `override` was in there. Edit: nevermind the second question, thanks for making me learn something new! – DCoder Nov 25 '12 at 14:18
  • Worth noting, that this forces the child to implement both `time` and `time_impl`. – SomeWittyUsername Nov 25 '12 at 14:18
  • @icepack why does the child have to implement time? – 111111 Nov 25 '12 at 14:18
  • @111111 Because this is the requirement and the defined interface – SomeWittyUsername Nov 25 '12 at 14:19
  • @icepack the child will inherit `time` from it's parent and meet whatever interface requirements there are, it works as expected here: http://ideone.com/eZBpyX – 111111 Nov 25 '12 at 14:20
  • @111111 I'm not talking about technicalities, I'm talking about the interface as defined by OP. Your solution, while forcing the default behavior, also requires the child to implement `time_impl` - this is a somewhat break of encapsulation since it dictates the child details of its private implementation. – SomeWittyUsername Nov 25 '12 at 14:23
  • @icepack I think we might differ on what's we consider good design, but I don't consider `private` to only encapsulate the inner workings of the class itself, using it to encapsulate the inner workings of a system like this if fine IMO. (That said, I personally would probably favour a template approach if I could at all get away with it). – 111111 Nov 25 '12 at 14:28
  • Such things are usually not something that can be played with freely. In a usual scenario you provide an interface (`time` here) and the client implements it in a way he feels right. Forcing the client to implement additional stuff to make the system work contradicts the concept of `interface`. – SomeWittyUsername Nov 25 '12 at 14:33
  • @Als I think in this context it's more important to mention the http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface – SomeWittyUsername Nov 25 '12 at 15:54
0

You can provide the default behavior in your base class by making your virtual function not pure virtual. However, you can't force the implementation to invoke this default behavior without posing some restrictions on child's implementation (see @111111 answer for details). You should inspect you requirements to see if this is an acceptable solution.

SomeWittyUsername
  • 18,025
  • 3
  • 42
  • 85