216

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?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
skydoor
  • 25,218
  • 52
  • 147
  • 201

10 Answers10

252

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).

Morwenn
  • 21,684
  • 12
  • 93
  • 152
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    You forgot to add why it surprises programmers : it is because inline definition is forbidden by standard. Pure virtual methods definitions must be `deported`. (either in a .inl or .cpp to refer to common file-naming practices). – v.oddou Sep 13 '13 at 02:35
  • so this calling method same as the static method member calling. Some sort of class method in Java. – Sany Liew Mar 03 '14 at 12:33
  • 2
    "not commonly used" == bad practice? I was looking for the exact same behaviour, trying to implement NVI. And NVI seems a good practice for me. – Uylenburgh Aug 17 '14 at 11:33
  • 7
    It's worth pointing out that making A::f() pure means that B *must* implement f() (otherwise B would be abstract and uninstantiable). And as @MichaelBurr points out, providing an implementation for A::f() means that B _may_ use it to define f(). – fearless_fool Jan 06 '15 at 05:46
  • 2
    IIRC, Scot Meyer has an excellent article about the use case of this question in one of his classic book "More effective C++" – irsis May 12 '15 at 16:58
  • Also note that in the pre-override days, this means if the base class `f()` signature changes, derived classes *must* be rewritten. So you don't get "orphan" `f`'s that look like they override the base `f` but don't actually. The price is that derived `f`s have to explicitly call the base, but that price was often worth it. – Yakk - Adam Nevraumont Dec 16 '19 at 16:31
  • I have code like the question. Header has f()=0; and below there is f(){cout <<"f";}. When I derive a class and override the f() I get multiple definition error. gcc 10.2 is rather new. From the discussion on this thread here, it shoudl be possible to do, why is it having problems? – MauriceRandomNumber Jun 17 '21 at 08:34
  • "seems to surprise most C++ programmers, even experienced ones". Why would that be? Does it entail any risky case, even if a corner one? Otherwise, if it allows for something some uses may need (even if uncommon cases), without associated risks/bad behavior, why would this be "surprising"? – sancho.s ReinstateMonicaCellio May 19 '23 at 12:55
96

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.

Terry Mahaffey
  • 11,775
  • 1
  • 35
  • 44
  • 13
    This is incorrect. If you invoke that pure virtual function at the constructor of your pure virtual class, a pure virtual call would be made. In which case you better have an implementation. – rmn Jan 18 '10 at 21:35
  • 1
    @rmn, Yes, you are right about virtual calls in constructors. I updated the answer. Hopefully everyone knows not to do that, though. :) – Terry Mahaffey Jan 18 '10 at 21:55
  • 3
    In fact, making a base pure call from a constructor results in implementation-defined behavior. In VC++, that amounts to a _purecall crash. – Ofek Shilon Jun 13 '10 at 21:30
  • @OfekShilon that is correct - I would be tempted to also call it undefined behavior and a candidate for bad practice/code refactoring (i.e. calling virtual methods inside the constructor). I guess it has to do with the virtual table coherency, which might not be prepared to route to the body of the correct implementation. – teodron May 18 '17 at 07:47
  • 1
    In constructors and destructors, virtual functions are *not* virtual. – Jesper Juhl Jul 04 '17 at 21:52
  • @rmn **"If you invoke that pure virtual function at the constructor of your pure virtual class...."** == undefined behavour – mada Oct 09 '21 at 09:33
  • @mada - i see nothing in the standard that would make this undefined behaviour. Calling a pure-virtual function in an abstract base-class is allowed and well-defined as long as that function does have a corresponding definition in that base-class. – ABaumstumpf Mar 17 '23 at 10:16
21

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; 
}
Kornel Kisielewicz
  • 55,802
  • 15
  • 111
  • 149
  • 1
    Base class destructors are always called anyway, virtual or not and pure or not; with other functions you can't guarantee that an overriding virtual function will call the base class implementation whether or not the base class version is pure. – CB Bailey Jan 18 '10 at 20:51
  • 1
    That code is wrong. You must define the dtor outside of the class definition due to a syntax quirk of the language. –  Jan 18 '10 at 21:19
  • @Roger : thanks, that actually helped me -- this is the code I've been using, it compiles fine under MSVC, but I guess it wouldn't be portable. – Kornel Kisielewicz Jan 18 '10 at 21:23
21

The advantage of it is that it forces derived types to still override the method but also provides a default or additive implementation.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    Why would I want to force if there is a default implementation? That sounds like normal virtual functions. If it was just a normal virtual function, I can either override and if I didn't, then the a default implementation will be provided (base's implementation). – StackExchange123 Mar 07 '20 at 12:09
8

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)

Basti
  • 3,998
  • 1
  • 18
  • 21
rmn
  • 2,386
  • 1
  • 14
  • 21
5

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.

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
4

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.

Yukiko
  • 1,113
  • 1
  • 8
  • 10
3

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 :-)

Nir Hedvat
  • 870
  • 7
  • 7
  • 8
    It does not need to be implemented in ALL derived classes, but it MUST have an implementation in all derived classes that you intend to instantiate. You cannot instantiate an object of type `C` in your example. You can instantiate an object of type `D` because it gets its implementation of `foo` from `B`. – YoungJohn Jul 30 '15 at 14:27
1

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";
       }
}
0

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.

TonySalimi
  • 8,257
  • 4
  • 33
  • 62