Use-Cases of Pure Virtual Functions with Body

Use-cases of pure virtual functions with body?

The classic is a pure virtual destructor:

class abstract {
public:
virtual ~abstract() = 0;
};

abstract::~abstract() {}

You make it pure because there's nothing else to make so, and you want the class to be abstract, but you have to provide an implementation nevertheless, because the derived classes' destructors call yours explicitly. Yeah, I know, a pretty silly textbook example, but as such it's a classic. It must have been in the first edition of The C++ Programming Language.

Anyway, I can't remember ever really needing the ability to implement a pure virtual function. To me it seems the only reason this feature is there is because it would have had to be explicitly disallowed and Stroustrup didn't see a reason for that.

If you ever feel you need this feature, you're probably on the wrong track with your design.

What's the use of the body of a pure virtual function in c++?

It is used in the exact way you mentioned in the question, that there is some common logic that can be reused by the derived classes but at the same time you want to force the derived classes to provide the implementation for the non-common part.

Can I avoid a pure virtual function with a body in this case

Sounds to me like all you really need is a virtual destructor for parent.

With a virtual dtor, deleting via a parent pointer the compiler will correctly call the derived class destructor.

It that's all you actually need and I understood your question correctly, then adding

 virtual ~parent() = default;

to your base class should do the trick.

What is the point of a pure-virtual member function with function body?

What are sensible use cases for this?

If the function has a sensible default implementation, or a partial implementation of whatever is relevant to the base class, but you still want to force derived classes to override it, that's a good place to put it.

Also, as noted in the comments, you might want to force a class with no pure virtual functions to be abstract. You can do this by making the destructor pure virtual; but the destructor must have a body, whether or not it's pure virtual.

when would A::foo ever be called?

It can only be called non-virtually; for example:

struct B : A {
void f(int i) const {
A::foo(i); // non-virtual call
// Do the B-specific stuff
}
};

why is this the correct/best implementation?

The alternative would be to invent a new name for the partial/default implementation, in addition to an unimplemented pure virtual function.

Are there any differences here between C++03 and C++11?

No.

Purpose of private pure virtual function?

So in general the pattern is to implement the public non-virtual function and the private or protected virtual function, it looks like you have researched this already, but this is generally known as the Template Method Pattern, with more explanations by Herb Sutter here and here.

Whether to make it pure virtual or not depends on your requirements, sometimes there is absolutely no default behavior that makes sense, or you want to force all the subclasses to implement their own version of this virtual function. Sometimes an empty implementation does make sense. Then provide, but what happens is that other implementors might forget to customize their classes, not implementing the virtual class for which you provided a default behavior. It is really a case by case decision that you will have to make.

There are some corner cases in which you will want to provide an implementation for a pure virtual function, Herb Sutter again, lists two, one to provide default behavior but force derived classes to conciously call, and the other is to protect against compiler issues that might get a pure virtual function called.

There are various concerns comming together at the point where your problem lies, in general make virtual functions private or protected, called by a public function (again Template Method Pattern). If derived classes don't need to call a superclasses implementation, make it private. If you want to implement default behavior make it protected and implement the default behavior in a higher class. If you want to force subclasses to implement their own function (independent of wether there is default behavior or not) make it pure virtual.

Pure virtual function with 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).

C++ pure virtual function have body

Your assumption that pure virtual function cannot be called is absolutely incorrect. When a function is declared pure virtual, it simply means that this function cannot get called dynamically, through a virtual dispatch mechanism. Yet, this very same function can easily be called statically, non-virtually, directly (without virtual dispatch).

In C++ language a non-virtual call to a virtual function is performed when a qualified name of the function is used in the call, i.e. when the function name specified in the call has the <class name>::<function name> form.

For example

struct S 
{
virtual void foo() = 0;
};

void S::foo()
{
// body for pure virtual function `S::foo`
}

struct D : S
{
void foo()
{
S::foo();
// Non-virtual call to `S::foo` from derived class

this->S::foo();
// Alternative syntax to perform the same non-virtual call
// to `S::foo` from derived class
}
};

int main()
{
D d;

d.S::foo();
// Another non-virtual call to `S::foo`
}

Why does C++ support pure virtual functions with an implementation?

C++ Supports pure virtual functions with an implementation so class designers can force derived classes to override the function to add specific details , but still provide a useful default implementation that they can use as a common base.

Classic example:

class PersonBase
{
private:
string name;
public:
PersonBase(string nameIn) : name(nameIn) {}

virtual void printDetails() = 0
{
std::cout << "Person name " << name << endl;
}
};

class Student : public PersonBase
{
private:
int studentId;
public:
Student(string nameIn, int idIn) : PersonBase(nameIn), studentId(idIn) { }
virtual void printDetails()
{
PersonBase::printDetails(); // call base class function to prevent duplication
std::cout << "StudentID " << studentId << endl;
}
};

Class with implementation of pure virtual function

Pure virtual functions are the virtual functions whose implementation must be provided by the derived class. This is one of the reason to make your virtual function pure, so that derived class must have it's implementation.

virtual void function()=0 is pure virtual function where =0 indicates it's purity.

When you have a pure virtual function in a class, you are not suppose to create a instance of class. (Otherwise making function pure virtual doesn't make much sense). Such a class is abstract class.

Now, there might be some cases where you want to have your own implementation of pure virtual function so that derived class may directly use it. Hence we provide body of pure virtual function in some cases.

If you want to create an instance of that class, don't make your virtual function pure.



Related Topics



Leave a reply



Submit