This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Under what circumstances is it advantageous to give an implementation of a pure virtual function?
Why do we need a pure virtual destructor in C++?
Compiler doesn't force the Child class to implement a destructor when its Base has pure virtual destructor.
struct Base
{
virtual void foo () = 0;
virtual ~Base() = 0;
};
Base::~Base() {} // necessary
struct Child : Base
{
void foo() {}
//ok! no destructor needed to create objects of 'Child'
};
Funny part is that; compiler rather forces the Base to define a destructor body. Which is understood. (Demo for reference)
Then what is the purpose of having pure virtual destructor in Base class ? (Is it just to disallow Base creating objects?)
Sometimes an abstract base class has no virtual methods (= often called a “mixin”) or no methods at all (= often called a “type tag”).
To force those classes to be used as abstract base classes, at least one method needs to be pure virtual – but the classes don’t have virtual methods! So we make the destructor pure virtual instead.
It makes the class abstract. The existance of at least a pure virtual method is sufficient for a class to be abstract.
If you don't have any other pure virtual functions in Base, you have the option to make the destructor pure virtual so that the base class is still abstract.
It actually does force the derived class to implement a destructor, but the compiler will do that for you if you don't provide one.
Ok, maybe I could have phrased this better. The second paragraph is in reply to:
Compiler doesn't force the Child class to implement a destructor when its Base has pure virtual destructor.
I probably wanted to say that a virtual destructor (pure or not) causes the derived class to also have a virtual destructor, whether you write it or the compiler does.
Compiler doesn't force the Child class to implement a destructor when
its Base has pure virtual destructor.
No, Compiler does generate a default destructor for Child class (which in turn calls the implementation of pure virtual destructor of class Base) in case you don't define one explicitly.
Related
Yes I have seen a lots of posts about using the keywords virtual and override for destructors in C++. I also think I understand the usage:
if a base class has a virtual destructor and a derived class overrides it, if the signatures are different, the program will not compile due to override.
However I am wondering - or I have seen it also several times in someones code, that it is used like this:
class Base
{
public:
~Base();
};
class Derived : public Base
{
public:
~Derived() override;
};
Does this override on a destructor of a non-virtual function in the base class actually has any impact on the program / compiling or anything? Or is it just used wrongly in that case?
You code doesn't compile because Base::~Base is not virtual.
Oh ok, maybe I have overseen this: if the Base class derives from
another class, say SuperBase class - which has a virtual destructor,
then the destructor of Base would be virtual without using the keyword
right?
Correct. If a method is virtual in a base class, then the method in the child class with the same name and same signature will also be implicitly virtual. virtual keyword can be omitted.
A good practice is to always use the keyword override on a method intended to override. This has two big advantages: it makes it clear to a human reader that the method is virtual and overrides and it avoid some bugs where the method is indented to override, but it silently doesn't (e.g. const mismatch).
Destructors are a special case in the sense that that they override a parent virtual destructor, even if they have different names.
I have a class which is abstract in that it defines common behaviour for concrete classes. As such, there is going to be no memory to clean up because the class cannot be instantiated. However, I am aware that you need a virtual destructor in order for the derived destructors to get called if their static type is the Base class.
Does this mean I should declare a virtual destructor for an abstract class always, but just leave the implementation empty?
You must provide a definition of every destructor in a class hierarchy, since all destructors up the inheritance graph do get called when a derived class is destroyed, even if some of the destructors are trivial.
Typically, you achieve this by putting virtual ~Base() { } (or some exception-specified variation thereof) in your base class. However, if the destructor is the only virtual member function and you want to make the base abstract, you can make the destructor pure-virtual, but you still have to define it:
struct Base
{
virtual ~Base() = 0;
};
Base::~Base() { }
Scott said on Effective C++, 3rd Edition, pg. 43 that to make an abstract class, we just need to give it a pure virtual destructor:
class AWOV { // AWOV = "Abstract w/o Virtuals"
public:
virtual ~AWOV() = 0; // declare pure virtual destructor
};
Then, he went on said that there is one twist: we must provide a definition for the pure virtual destructor:
AWOV::~AWOW() {} // definition of pure virtual dtor
My question is, by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.
Why is it OK to provide a definition (even it is empty) for the pure virtual destructor here?
"we are saying that the function cannot have any definition for the class where this pure virtual function is declared."
That's not what pure virtual means. Pure virtual only means that the containing class cannot be instantiated (is abstract), so it has to be subclassed, and subclasses must override the method. E.g.,
struct A {
virtual ~A() = 0;
};
A::~A() {}
struct B : A {};
int main()
{
A a; // error
B b; // ok
}
Here, the B destructor is implicitly defined. If it was another method that is pure virtual, you'd have to explicitly override it:
struct A {
virtual void foo() = 0;
};
void A::foo() {}
struct B : A {};
int main()
{
B b; // error
}
Providing a definition for a pure virtual method is desirable when the base class must be abstract but still provide some default behavior.
In the specific case of a destructor, it has to be provided because it will be called automatically when subclass instances are destroyed. A program that tries to instantiate a subclass of a class with a pure virtual destructor without a definition will not pass the linker.
Making it pure forces derived (non-abstract) classes to implement their own.
Providing an implementation allows derived classes to invoke base class behavior (which destructors do by default).
There are 2 cases.
Pure virtual destructor
This case is specifically treated by the standard.
12.4 Destructors [class.dtor]
9) A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any
derived class are created in the program, the destructor shall be defined. If a class has a base class with a
virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
The case of the destructor is different because all destructors are called in an inheritance hierearchy (assuming correct deletion) in reverse order of construction, even if not explicitly. So the base class destructor is called when the object gets deleted - that's why it needs an implementation.
Pure virtual method
These differ from destructors in that they're not required to be implemented, nor do they need an implementation. The difference for the missing requirement is that when a Derived::foo() gets called, it doesn't automatically call Base::foo() (not that it could, since it can or can not be implemented).
Why you would want to implement a pure virtual method depends on the case. I look at the pure specifier as a hint to the programmer, as opposed to related to the logic. It tells you - the programmer - that you should implement that method. It doesn't really matter if the base class has an implementation or not.
by specifiying = 0, for pure virtual functions, we are saying that the function cannot have any definition for the class where this pure virtual function is declared.
Not really. You're saying derived non-abstract classes have to override that function. This doesn't prevent you from implementing it yourself.
This is not necessary for all pure virtual functions. Not at all.
This way, the derived classes will still be forced to override the implementation, but there will be a default implementation in the base class, in case you need to call it. And that's the case here - because you're dealing with a destructor: when a derived object is being destroyed, its destructor is called and its base classes destructors are called as well. That's why you need an implementation for A::~A.
By making a function pure virtual we force the user of the class to replace the function with another in the derived class.
The base class function can still be called with BaseClass::myfunction(...)
Now the base class might want to provide some core functionality that the derived class may use if it chooses to do so.
Correct answer:
Suppose there are 2 pure virtual functions in class. Now assume that both have implementation. The reason for providing implementation for PVF is that the Base class method can act as default behavior if Base class is derived by child by implementing these PVF methods(to make class as concrete)
The pure virtual destructor in base class should have a definition. Otherwise compiler will generate a call to base class destructor from the derived class destructor during link-time and will cause a link-error.
I tried to define the pure virtual destructor inside the base class like below:
class base
{
public:
base()
{
cout << "constructor in base class\n";
}
virtual ~base()=0
{}
};
This gave the compilation error:
error: pure-specifier on function-definition
Then i tried to define the function outside the base class like below:
class base
{
public:
base()
{
cout << "constructor in base class\n";
}
virtual ~base()=0;
};
base::~base()
{
}
This removes the compilation error and it behaves as my understanding.
But my question is how does defining the pure virtual destructor outside the base class removes the compilation error?
Your second example is correct.
A lot of the other answers assume that it is illegal to have a pure virtual function with a default implementation, however that is incorrect.
In the case of a pure virtual destructor you must have a definition (see the link in xmoex answer).
It is true that:
§10.4/2 a function declaration cannot provide both a pure-specifier
and a definition
However, as you noticed it possible to provide a definition outside of the declaration.
i looked at this page:
http://www.gotw.ca/gotw/031.htm
and from my understanding a pure virtual destructor must have a definition (even an empty one) as every derived class has to call the base classes destructor
It is invalid syntax to write:
virtual ~base()=0
{}
If you want to supply implementation of a pure virtual member function, you should do it outside of the class. Most of the time you should not do this, since pure virtual functions should never be called anyhow. It is however possible to define implementation for pure virtual functions.
In fact, a pure virtual destructor must have an implementation. This is because destructors of all base classes are called on object destruction regardless of whether destructor in a given class is pure virtual or not.
Thus, if you create an instance of any of the classes derived from base then at some point destructors of all classes to which the object belongs will be called including the base::~base() destructor. If you do not define it, the linker will not find a required symbol and will complain.
The destructor is the only method that even if it is pure virtual, has to have an implementation in order for the class it's defined in to be useful. So in contrast to #Kiril's answer I would say that pure virtual functions can have implementations.
Somewhat off topic :
struct base {
virtual void func() = 0;
};
void base::func() { /* default implementation */ }
class derived : public base{
void func() { base::func(); } // have to explicitly call default implementation.
};
Pure virtual methods can have implementations, but they make the base class abstract and force deriving classes to overwrite those methods.
Say you have a pointer member in the base class. You want to delete it on the destructor but also make the class abstract - so you implement to pure virtual destructor.
This is an implementation detail - the fact that the destructor is implemented should't be visible from the outside.
Inspired by: C++ -- why should we define the pure virtual destructor outside the class definition?
What does the following code actually do?
class Object
{
public:
virtual ~Object() = 0;
};
Object::~Object() { /*...*/ }
I thought that the point of a pure virtual function was to force subclasses to implement that particular function. If that is the case, then why bother implementing the same function in the virtual base class?
This code prevents you from creating an instance of Object, while at the same time allowing you to create subclasses.
When destroying an object, the destructor of the parent class will be called, so it must exist. This applies whether the destructor is pure virtual or not. A pure virtual member function only needs to be defined if you explicitly call it, Foo:theFunc().
In the case of a pure virtual destructor, there is no way of 'forcing' anyone to implement it in derived classes. The compiler will write one for you. In addition, the compiler written destructor (in a derived class) will call the parent destructor - so you had better have written an implementation for the parent.
So, to summarise:
A pure virtual function that is not a destructor need not have an implementation as you would not expect a programmer to call it.
A pure virtual destructor must have an implementation since the compiler is bound to call it from destructors (both programmer and compiler written) in child classes.