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.
Related
I have an abstract base class, which serves the purpose of allowing an array of pointers to a base class to be created. (Useful for 'many things'...)
My abstract base class contains no member functions. Therefore there are no pure virtual methods, and therefore I guess it is not technically abstract.
However, I do not want to be able to create an instance of this class.
Is it possible to create a memberless abstract base class? If not, is there another resolution to preventing an instance of my "abstract base" from being created? Will making the constructor protected suffice?
It has been pointed out to me that actually, an abstract base class would not be required if the purpose of that class was to allow a vector or array of pointers to the base class to be created - one could simply not have a base class and use as the base class the class at the top of the inheritance hierarchy. Alternatively, one could copy and paste that top class and exchange the implemented methods for pure virtual functions with no implementation, however this seems logically inconstant with the idea of abstract base pointers, and would lead to more difficult to maintain code.
Provide a pure virtual destructor:
struct Base {
virtual ~Base() = 0;
};
inline Base::~Base() {}
You need to provide an implementation, which you could right in the header by making it inline.
An abstract class is a class with some pure virtual function:
[...] A class is abstract if it has at least one pure virtual function. [...]
[N4431 §10.4/2]
Since you want an array of pointers to instances of (classes derived from) your abstract class, I assume you also want to be able to eventually delete and thus destruct one or more of those instances via these pointers:
Base * instance = // ... whatever ...
delete instance;
To call the correct destructor (of the derived class) in that case, the destructor has to be virtual.
So since it's virtual either way, and you don't want some pure virtual member function, it's best to make the destructor pure virtual.
To make a virtual function pure, you append the pure-specifier to its declaration:
struct Foo {
virtual void bar(void) /* the */ = 0; // pure-specifier
};
Now, regarding the definition, you wonder why we need to provide one, since ...
[...] A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1). [...]
[N4431 §10.4/2]
This is because when destructing a derived class, after the derived classes destructor has been called, the destructors of the bases classes will also be called:
struct Derived : public Base {
~Derived() {
// contents
// Base::~Base() will be called
}
};
After executing the body of the destructor [...] a destructor for class X calls [...] the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name [...]
[N4431 §12.4/8]
So a definition of the pure virtual destructor if the Base class is needed. However ...
[...] A function declaration cannot provide both a pure-specifier and a definition [...]
[N4431 §10.4/2]
... so it has to be defined outside of the class definition. This could be done in a separate source file, or thanks to ...
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case [...]
[N4431 §7.1.2/4]
... as a inline function in the header.
The standard is even explicit about the requirement of a definition in this case:
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. [...]
[N4431 §12.4/9]
Is it possible to create a memberless abstract base class?
The simplest way is to make the destructor pure virtual.
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
};
If you are going to delete instances of that class polymorphically, then you must have a virtual destructor anyway. It's not just to prevent instantiations of the base class, it's required to avoid undefined behaviour. Just make it pure virtual. And give it an empty implementation (yes, this works in C++).
If, however, you are not using polymorphism at all, then you should avoid adding a virtual destructor and instead just make the constructor protected. Remember that a base class does not necessarily have to establish a polymorphic class hierarchy (see examples in the C++ library like std::input_iterator_tag).
I know the cases where pure virtual destructors are needed. I also know that If we don't provide an implementation for them it will give me a linker error. What I don't understand is why this should be the case in a code fragment as shown below:
int main()
{
Base * p = new Derived;
}
Here there is no delete, so no call to destructor and so no need for its implementation(assuming it is supposed to behave like other normal functions which are declared but not defined, linker complains only when we call them)...or am I missing something?
I need to understand why this should be a special case?
Edit: based on comments from BoBTFish
Here are my Base and Derived classes
class Base
{
public:
Base(){}
virtual ~Base() = 0;
};
class Derived : public Base
{
};
The compiler tries to build the virtual table given a virtual (pure or not) destructor, and it complains because it can't find the implementation.
virtual destructors differ from other virtual functions because they are called when the object is destroyed, regardless of whether it was implemented or not. This requires the compiler to add it to the vf table, even if it's not called explicitly, because the derived class destructor needs it.
Pedantically, the standard requires a pure virtual destructor to be implemented.
C++11 standard:
12.4 Destructors
Paragraph 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.
Destructors differ from other virtual functions in this way, because they are special and automatically invoked in bases, with no possible, useful or meaningful way to prevent it.
[C++11: 12.4/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.
Bases are always destroyed, and to do this, a base destructor definition is required. Conversely, other overridden virtual functions are not invoked automatically at all. Hence the special-case requirement.
struct Base
{
virtual ~Base() = 0; // invoked no matter what
virtual void foo() = 0; // only invoked if `Base::foo()` is called
};
Base::~Base() {}
/* void Base::foo() {} */
struct Derived : Base
{
virtual void foo() { /* Base::foo(); */ }
};
int main()
{
std::unique_ptr<Base> ptr(new Derived());
}
One practical reason is that destructors come first in the list of virtual member functions in the vtable in practically all implementations. And implementations tend to define the vtable itself when it defines the first virtual member function. So, no destructor, no vtable. And the vtable is critical.
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)
This may seem like a simple question, but I can't find the answer anywhere else.
Suppose I have the following:
class Abstract {
public:
virtual void foo() = 0;
virtual void bar();
}
class Derived : Abstract {
public:
virtual void foo();
}
Is it ok that class Derived does not implement the bar() function?
What if not ALL of my derived classes need the bar() function, but some do.
Do all of the virtual functions of an abstract base class need to be implemented in the derived classes, or just the ones that are pure virtual?
Thanks
Derived classes do not have to implement all virtual functions themselves. They only need to implement the pure ones.1 That means the Derived class in the question is correct. It inherits the bar implementation from its ancestor class, Abstract. (This assumes that Abstract::bar is implemented somewhere. The code in the question declares the method, but doesn't define it. You can define it inline as Trenki's answer shows, or you can define it separately.)
1 And even then, only if the derived class is going to be instantiated. If a derived class is not instantiated directly, but only exists as a base class of more derived classes, then it's those classes that are responsible for having all their pure virtual methods implemented. The "middle" class in the hierarchy is allowed to leave some pure virtual methods unimplemented, just like the base class. If the "middle" class does implement a pure virtual method, then its descendants will inherit that implementation, so they don't have to re-implement it themselves.
Only the pure virtual methods have to be implemented in derived classes, but you still need a definition (and not just a declaration) of the other virtual methods. If you don't supply one, the linker might very well complain.
So, just putting {} after your optional virtual method gives you an empty default implementation:
class Abstract {
public:
virtual void foo() = 0; // pure virtual must be overridden
virtual void bar() {} // virtual with empty default implementation
};
class Derived : Abstract {
public:
virtual void foo();
};
A more involved default implementation would go into a separate source file though.
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined.
Simply put the rule is:
If your derived class overiddes the Base class virtual method then it should provide a definition as well, If not then the Base class should provide the definition of that method.
As per the above rule in your code example, virtual void bar(); needs a definition in the Base class.
Reference:
C++03 Standard: 10.3 Virtual functions [class.virtual]
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).
So either you should make the function pure virtual or provide a definition for it.
The gcc faq doccuments it as well:
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.
Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.
Yes, that's fine ... you only need to implement any pure virtual functions in order to instantiate a class derived from an abstract base class.
Yes, Its correct that a Derived class has to OVERRIDE the function which is Pure Virtual in the Parent Class. Parent class having a Pure Virtual Function is called Abstract Class only because it's Child class must give their own body of the Pure Virtual Function.
For the Normal Virtual Functions:-
Its not necessary to override them further, as some child class may have that function, some may not have.
Main purpose of Virtual Function mechanism is Run Time Polymorphism, whether main purpose of Pure Virtual Function(Abstract Class) is to make it mandatory to have the same name Function with own's body.
Compiler is giving link error and require to provide definition for Base pure virtual destructor.
class Base
{
public:
virtual ~Base() = 0;
};
class Derived : public Base
{
public:
virtual ~Derived(){ std::cout << "Derived dtor"; }
};
int main()
{
Derived d;
}
Just provide an empty implementation for it (outside the class definition):
Base::~Base() { }
Being pure-virtual just means that you must override the member function in any concrete derived class; it doesn't mean that it cannot have a body. In the case of the destructor, you must supply a body, wether the destructor is pure-virtual or not, since it is invoked by the compiler when you destroy the object.
Just to be clear, you must provide an implementation. Whether it is empty or not is up to you. This is because the compiler generates code that calls the destructor whenever you try to destroy an instance of Base. You could declare a normal virtual Base:
virtual ~Base();
And never define it. This would be fine as long as you never destroy an instance of Base (questionable conduct, but it would work). However, in your case, Base has a Derived type, which calls the Base class's destructor in its own destructor. That's where your linker error is coming from.
Yes. There's a non-virtual call of Base::~Base, implicitly from Derived::~Derived. Therefore the compiler is right to complain that Base::~Base must be defined, even if empty.
Since Derived inherits Base, destroying a Derived object will first call Derived::~Derived and then Base::~Base (the compiler does this for you - whether you like it or not).
Hence, you have to provide an implementation for Base::~Base. Note that this isn't particularly strange. A pure virtual function can have an implementation. 'pure virtual' only means that the class cannot be instantiated.