views:

544

answers:

6

In C++, it is legal to give an implementation of a pure virtual function:

class C
{
public:
  virtual int f() = 0;
};

int C::f() 
{
  return 0;
}

Why would you ever want to do this?

Related question: The C++ faq lite contains an example:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0;
};

inline Funct::~Funct() { }  // defined even though it's pure virtual; it's faster this way; trust me

I don't understand why the destructor is declared pure virtual and then implemented; and I don't understand the comment why this should be faster.

+9  A: 

Declared destructors must always be implemented as the implementation will call them as part of derived object destruction.

Other pure virtual functions may be implemented if they provide a useful common functionality but always need to be specialized. In the case, typically derived class implementations will make an explicit call to the base implementation:

void Derived::f()
{
    Base::f();

    // Other Derived specific functionality
}

Typically, you make a destructor virtual if you need to make a class abstract (i.e. prevent non-derived instances from being created) but the class has no other functions that are naturally pure virtual. I think the 'trust me it's faster' is refering to the fact that because destructors called as part of derived object clean up don't need to use a vtable lookup mechanism, the inline implementation can be taken advantage of, unlike typical virtual function calls.

Charles Bailey
+2  A: 

If you have so common functionality that derived class can utilize. But they need do other work as-well.

So the derived class implements the virtual function and calls the underlying base version:

class X: public C
{
    public:
        virtual int f()
        {
            return C::f() + 1; // I am +1 over my parent.
        }
};
Martin York
A: 

Because it's regarded as ill formed to write:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0 {};
};

The destructor will still be called if you derive from this class. Declaring all methods pure virtual is just for clarity. You might as well write it like this:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() {};
};

The class will still be abstract since at least one method is pure virtual. The destructor is also still inline.

Magnus Skog
A: 

G'day,

Concerning providing a default implementation for a member function declared in a base class, the only reason I can think of at the moment is where you want to provide a default implementation of the behaviour as a possible implementation choice for someone who is specialising the base class.

The author of the derived class can chose to use the default implementation provided by the base class author instead of adding their own specialised implementation.

This is generally the case where people object to having separate functions to provide an interface and a default implementation of the behaviour yet they still want separation between default implementation and the associated interface.

Ah, just saw @Martin York's post which provides an example.

Actually, Scott Meyers discusses this in his book "Effective C++". It's Item 36 in the 1st edition.

HTH

cheers,

Rob Wells
+1  A: 

Just found out that Herb Sutter answered the first part of this question in his Guru of the Week #31.

Tobias
A: 

Regarding the speed of the virtual destructor this is because the destructor is defined in the cpp file and not the header. It has more to do with size than speed. It is explained in detail in "Large-Scale C++ Software Design". Unfortunately I cannot remember all the details, but I think inline virtual functions get defined multiple times in the vtable.

There is a discussion this here: Are inline virtual functions really a non-sense?

iain