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

I did a simple test today:
struct C{virtual void f()=0;};
void C::f(){printf("weird\n");}
The program is OK, but is weird to me, when we use =0 it means the function body should be defined in the inherited classes, but it seems I can still give it implementation function.
I tried both GCC and VC, both OK. So it seems to me this should be part of C++ standard.
But why this is not a syntax error?
A reason I could think of is like C# having both 'interface' and 'abstract' keywords, interface can't have an implementation, while abstract could have some implementations.
Is this the case for my confusion, that C++ should support such a kind of weird syntax?

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

Others mentioned language consistency with the destructor, so I'll go for a software engineering stand-point:
It's because the class you are defining may have a valid default implementation, but calling it is risky/expansive/whatever. If you don't define it as pure virtual, derived classes will inherit that implementation implicitly. And may never know until run-time.
If you define it as pure virtual, a derived class must implement the function. And if it's okay with the risk/cost/whatever, it can call the default implementation statically as Base::f();
What's important is that it's a conscious decision, and the call is explicit.

Basically, the best of both worlds (or the worst...).
The derived class is required to implement the pure virtual method, the designer of the base class requires this for some reason. And the base class also provides a default implementation of this method that, if the derived class desires or requires it, can be used.
So some sample code could look like;
class Base {
public:
virtual int f() = 0;
};
int Base::f() {
return 42;
}
class Derived : public Base {
public:
int f() override {
return Base::f() * 2;
}
};
So what is a common use case...
A common use case for this technique is related to the destructor - basically the designer of the base class desires that it is an abstract class, but none of the methods make much sense as being pure virtual functions. The destructor is a feasible candidate.
class Base {
public:
~Base() = 0;
};
Base::~Base() { /* destruction... */ }

A pure virtual function must be overriden in subclasses. However, you can provide a default-implementation, that will work for sub-classes, but might not be optimal.
A constructed use case is for abstract shapes, e.g.
class Shape {
public:
virtual Shape() {}
virtual bool contains(int x, int y) const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual int area() const = 0;
}
int Shape::area() const {
int a = 0;
for (int x = 0; x < width(); ++x) {
for (int y = 0; y < height(); ++y) {
if (contains(x,y)) a++;
}
}
return a;
}
The area method will work for any shape, but is highly inefficient. Subclassers are encouraged to provide a suitable implementation, but if there is none available, they still can explicitely call the base class's method

Pure virtual means "child must override".
So:
struct A{ virtual void foo(){}; };
struct B:A{ virtual void foo()=0; };
struct C:B{ virtual void foo(){}; };
struct D:C{ virtual void foo()=0; };
void D::foo(){};
struct E:D{ virtual void foo(){D::foo();}; };
A has a virtual foo.
B makes it abstract. Before making an instance, derived types must implement it now.
C implements it.
D makes it abstract, and adds an imllementation.
E implements it by calling D's implementation.
A, C and E can have instances created. B and D cannot.
The technique of abstract with implementation can be used to provide a partial or inefficient implementation that derived types can call explicitly when they want to use it, but do not get "by default" because that would be ill advised.
Another intersting use case is where the parent interface is in flux, and tue code base is large. It has a fully functional implementation. Children who use the default must repeat the signature and forward explicitly to it. Those that want to override simply override.
When the base class sigrnature changes, the code will fail to compile unless every child either explicitly calls the default or properly overrides. Prior to the override keyword this was the only way to ensure you did not accidentally create a new virtual function instead of overriding a parent, and it remains the only way where the policy is enforced in the parent type.

Please note that you cannot instantiate an object with pure virtual methods.
Try to instantiate:
C c;
with VC2015, there is an error as expected:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): error C2259: 'C': cannot instantiate abstract class
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: due to following members:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: 'void C::f(void)': is abstract
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(6): note: see declaration of 'C::f'
To answer your question:
The mechanisms only declares the function to be pure virtual, but there is still the virtual function table and the baseclass. It will avoid you instanciate Baseclass (C), but does not avoid using it:
struct D : public C { virtual void f(); };
void D::f() { printf("Baseclass C::f(): "); C::f(); }
...
D d;
d.f();

The destructor must be defined, even if it is pure virtual. If you don't define the destructor the compiler will generate one.
Edit: you can't leave destructor declared without define, will cause link error.

You can anyway call the body of the function from derived classes.
You can implement the body of a pure virtual function to provide a default behavior, and at the same time you want that the designer of the derived class use that function explicitly.

Related

What are the advantages of having a definition of pure virtual method In C++? [duplicate]

I did a simple test today:
struct C{virtual void f()=0;};
void C::f(){printf("weird\n");}
The program is OK, but is weird to me, when we use =0 it means the function body should be defined in the inherited classes, but it seems I can still give it implementation function.
I tried both GCC and VC, both OK. So it seems to me this should be part of C++ standard.
But why this is not a syntax error?
A reason I could think of is like C# having both 'interface' and 'abstract' keywords, interface can't have an implementation, while abstract could have some implementations.
Is this the case for my confusion, that C++ should support such a kind of weird syntax?
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;
}
};
Others mentioned language consistency with the destructor, so I'll go for a software engineering stand-point:
It's because the class you are defining may have a valid default implementation, but calling it is risky/expansive/whatever. If you don't define it as pure virtual, derived classes will inherit that implementation implicitly. And may never know until run-time.
If you define it as pure virtual, a derived class must implement the function. And if it's okay with the risk/cost/whatever, it can call the default implementation statically as Base::f();
What's important is that it's a conscious decision, and the call is explicit.
Basically, the best of both worlds (or the worst...).
The derived class is required to implement the pure virtual method, the designer of the base class requires this for some reason. And the base class also provides a default implementation of this method that, if the derived class desires or requires it, can be used.
So some sample code could look like;
class Base {
public:
virtual int f() = 0;
};
int Base::f() {
return 42;
}
class Derived : public Base {
public:
int f() override {
return Base::f() * 2;
}
};
So what is a common use case...
A common use case for this technique is related to the destructor - basically the designer of the base class desires that it is an abstract class, but none of the methods make much sense as being pure virtual functions. The destructor is a feasible candidate.
class Base {
public:
~Base() = 0;
};
Base::~Base() { /* destruction... */ }
A pure virtual function must be overriden in subclasses. However, you can provide a default-implementation, that will work for sub-classes, but might not be optimal.
A constructed use case is for abstract shapes, e.g.
class Shape {
public:
virtual Shape() {}
virtual bool contains(int x, int y) const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual int area() const = 0;
}
int Shape::area() const {
int a = 0;
for (int x = 0; x < width(); ++x) {
for (int y = 0; y < height(); ++y) {
if (contains(x,y)) a++;
}
}
return a;
}
The area method will work for any shape, but is highly inefficient. Subclassers are encouraged to provide a suitable implementation, but if there is none available, they still can explicitely call the base class's method
Pure virtual means "child must override".
So:
struct A{ virtual void foo(){}; };
struct B:A{ virtual void foo()=0; };
struct C:B{ virtual void foo(){}; };
struct D:C{ virtual void foo()=0; };
void D::foo(){};
struct E:D{ virtual void foo(){D::foo();}; };
A has a virtual foo.
B makes it abstract. Before making an instance, derived types must implement it now.
C implements it.
D makes it abstract, and adds an imllementation.
E implements it by calling D's implementation.
A, C and E can have instances created. B and D cannot.
The technique of abstract with implementation can be used to provide a partial or inefficient implementation that derived types can call explicitly when they want to use it, but do not get "by default" because that would be ill advised.
Another intersting use case is where the parent interface is in flux, and tue code base is large. It has a fully functional implementation. Children who use the default must repeat the signature and forward explicitly to it. Those that want to override simply override.
When the base class sigrnature changes, the code will fail to compile unless every child either explicitly calls the default or properly overrides. Prior to the override keyword this was the only way to ensure you did not accidentally create a new virtual function instead of overriding a parent, and it remains the only way where the policy is enforced in the parent type.
Please note that you cannot instantiate an object with pure virtual methods.
Try to instantiate:
C c;
with VC2015, there is an error as expected:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): error C2259: 'C': cannot instantiate abstract class
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: due to following members:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: 'void C::f(void)': is abstract
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(6): note: see declaration of 'C::f'
To answer your question:
The mechanisms only declares the function to be pure virtual, but there is still the virtual function table and the baseclass. It will avoid you instanciate Baseclass (C), but does not avoid using it:
struct D : public C { virtual void f(); };
void D::f() { printf("Baseclass C::f(): "); C::f(); }
...
D d;
d.f();
The destructor must be defined, even if it is pure virtual. If you don't define the destructor the compiler will generate one.
Edit: you can't leave destructor declared without define, will cause link error.
You can anyway call the body of the function from derived classes.
You can implement the body of a pure virtual function to provide a default behavior, and at the same time you want that the designer of the derived class use that function explicitly.

Pure virtual function in class implementation [duplicate]

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?
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).
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.
The advantage of it is that it forces derived types to still override the method but also provides a default or additive implementation.
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;
}
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)
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.
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.
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 :-)
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";
}
}
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.

Rules for deriving from a non-virtual descendant with virtual base class

If I have a hierarchy of C++ classes where the base class has a member function that is declared as virtual, but derived classed do not declare that function as virtual, how far into the class hierarchy does the virtualization carry. For example, given the code is the return value of MyFunc2 well defined?
class A
{
public:
virtual int x() { return 1; }
}
class B : public A
{
public:
int x() { return 2; }
};
class C: public B
{
public:
int x() { return 3; }
};
int MyFunc1(f &A)
{
return f.x();
}
int MyFunc2(f &B)
{
return f.x();
}
int MyFunc3()
{
C c;
return MyFunc1(c);
}
int MyFunc4()
{
C c;
return MyFunc2(c);
}
From similar question here, it would appear that the virtual characteristic is propagated forward to all classes once it is virtual in the base class, but I'm wondering how well defined this is, specifically is B.x() virtual by implication of being derived from A.
Overrides in subclasses are implicitly virtual too. You can specify the virtual keyword again, but it does not make any difference, although it's often considered good practice. It is absolutely "well defined" in the standard.
Starting C++11, you have an even better option: you can tag virtual methods in subclasses with override to ensure they actually override something. This prevent not actually overriding parent methods because of a small prototype difference and will trigger errors if you change the base virtual prototype but forget to adapt the overrides.
Yes, the virtual characteristic is "propagated" (to use your wording) to all derived classes. If derived classes declare and define a member function with the same signature as an inherited virtual function, they override it.
C++11 introduced the final modifier which derived classes can use to prevent their descendents from further-overriding an inherited virtual function. However, the function is still technically virtual (e.g. given a pointer to base, a polymorphic call of p->func() calls the func() corresponding to the actual type of the object) .... it just cannot be overridden.

override c++ virtual method

I have a class template where some methods are defined as virtual to give the ability for the user of my class to give an implementation for them in his derived class. Note that in my template class there is some non-virtual methods that makes use of the virtual one (a virtual class that should return a value is called in a non-virtual class).
Can you give me a simple example of a correct code where the virtual method of the parent class should return a value (but it's implementation is provided in a child class) and the value returned by the virtual method in the parent class is used in other methods of that class. Because I saw somewhere (for example here: Safely override C++ virtual functions) that this can cause some problems and the user defined method will note override the virtual method of the parent class.
Note: I program with Code::Blocks using g++ compiler.
EDIT: as requested here a simple example of what I want:
template<typename T>
class parent {
public:
// Public methods that user can call
int getSomething(T t);
void putSomething(T t, int x);
// public method that user should implement in his code
virtual float compute(T t) { }
// protected or private methods and attributes used internally by putSomething ...
float doComplexeThings(...); // this can call
};
The method compute() should be implemented by the user (the child class). However, this method compute() is called by putSomething() and doComplexeThings() for example.
If you can use C++11 features in your compiler then overrides can be tagged as so with the override special identifier:
float compute() override;
The above line in a derived class will cause a compiler error as the function does not override a member function in the base (incorrect signature, missing argument). But note that this must be done in each derived class, it is not a solution that you can impose from the base class.
From the base class you can only force the override by making the function pure virtual, but that changes the semantics. It does not avoid problems while overriding, but rather forces overriding in all cases. I would avoid this approach, and if you are to follow it and there is a sensible implementation for the base type, make the function virtual and provide a definition so that your derived classes's implementation can just call the functions the base type (i.e. you force the implementation, but in the simplest cases it will just forward the call to the parent)
You just have to make sure that the methods have the same signature (including const/mutable modifiers and argument types). You can use a pure virtual definition to provoke compiler errors if you fail to override the function in a subclass.
class parent {
public:
// pure virtual method must be provided in subclass
virtual void handle_event(int something) = 0;
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
class incomplete_child : public parent {
public:
virtual void handle_event(int something) const {
// does not override the pure virtual method
}
};
int main() {
parent *p = new child();
p->handle_event(1); // will call child::handle_event
parent *p = new incomplete_child(); // will not compile because handle_event
// was not correctly overridden
}
This question is asked in 2013. It's pretty old but I found something new which doesn't exist in the answers.
We need to understanding three concept is overload, overwrite, and hide.
Short answer, you want to overload the inheritance function from base class.
However, overload is the mechanism to add multiple behavior for function which needs all these functions under the same scale. But the virtual function is in the Base class obviously.
class A {
public:
virtual void print() {
cout << id_ << std::endl;
}
private:
string id_ = "A";
};
class B : A {
public:
using A::print;
void print(string id) {
std::cout << id << std::endl;
}
};
int main(int argc, char const *argv[]) {
/* code */
A a;
a.print();
B b;
b.print();
b.print("B");
return 0;
}
Add using A::print; in your derive class will do the work!
Though I don't feel it's a good idea since the philosophy behind the overload and inheritance is different, it may not a good idea to nest them together.

Pure virtual function with implementation

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?
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).
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.
The advantage of it is that it forces derived types to still override the method but also provides a default or additive implementation.
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;
}
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)
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.
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.
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 :-)
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";
}
}
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.