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`
}
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.
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.
Adding a body to a pure virtual/abstract function in C++?
Pure virtual function can have a body, but the fact that you declare them pure virtual is exactly to say that a derived implementation is required.
You can execute the pure virtual method from a derived method (using an explicit BaseClass::method()
) but still you have to provide an implementation.
Not being able to instantiate a class with a pure virtual method that has not been overriden is the main point of the pure virtual declaration. In other words the idea of declaring a method pure virtual is to ensure that the programmer will not forget about providing its implementation.
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.
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.
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;
}
};
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).
Related Topics
Does (W)Ifstream Support Different Encodings
If Temporaries Are Implicitly Non-Modifiable, How Does This Work
How to Securely Disconnect an Asio Ssl Socket
Why "Initializer-String for Array of Chars Is Too Long" Compiles Fine in C & Not in C++
Does Case-Switch Work Like This
Why Does 'Int ;' Compile Fine in C, But Not in C++
Lifetime of Lambda Objects in Relation to Function Pointer Conversion
How to Select a Random Element in Std::Set
Std::Vector of Std::Vectors Contiguity
C++ Abstract Class Without Pure Virtual Functions
Generate Include File Name in a MACro
C++ Terminate Called Without an Active Exception
Where Are the Man Pages for C++
Performance Hit from C++ Style Casts
Format Specifiers for Uint8_T, Uint16_T, ...
Passing a Pointer Representing a 2D Array to a Function in C++