I am having trouble understanding virtual functions. When I overload a virtual function, is the new derived function called only? Or both derived and base functions? Because I noticed that when virtual destructors are called, the base AND the derived class destructors are called.
destructors are special member functions in this particular regards.
If you have a virtual base class destructor then it will properly call Base as well as derived class destructors during polymorphic deletion(calling delete on base class pointer pointinf to derived class object.).
However, Other virtual member functions do not share the same special status as destructors. Only the function defined for the appropriate object type gets called. If you need any other function to be called you need to do so explicitly.
a derived class object is nothing but a kind of wrapper to the base class object.
So in case of destructors,both the destructors should be called which is an expected behaviour.
In case of virtual function, you are given a chance to replace the function in a base class.so using a base class pointer to hold a derived class object will only call the virtual function in the derived class.
Related
Note: I am not asking why a parent class need to have virtual method.
I remember something coding guideline like that(I don't remember well and just try to express as my own word,hope I have correct wording): if the parent class have virtual method,the derived class should also at least have one virtual method, even the derived class would not have derived class from itself, if the derived class really no need to have any virtual method, set destructor as virtual. The reason behind it is something like "prevent duplicate virtual table", what is it talking about?
And I also remember a related example like that:
class A{
virtual f();
};
class B : public A{
};
B as no derived class, if B has no virtual method, the consequence is something like "any place that include B will have a duplicate virtual table generated by compiler" (also is just expressed from my impression), what is the meaning of that (if it is true)?
Note the following:
If the base class has a virtual member function other than a destructor, the derived class inherits that function.
If the base class declares a member function as virtual, and the derived class declares a member function of the same name with the same argument types, then the derived class function is automatically virtual, and overrides the base class's function.
If the base class has a virtual destructor, the derived class's destructor is automatically virtual, whether user-declared or not, and overrides the base class's destructor.
The example you gave is not in any way problematic. I would advise you to forget everything you think you remember about this coding standard.
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 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() { }
I know you shouldn't call any virtual function in the ctor or dtor of the base class, but what about from that of the most derived class? Should be fine right? E.g.
class base {
...
virtual void free() = 0;
};
class child : public base {
...
free() {/* free memory */}
~child() {free();}
};
Well, you can do it, but the dynamic type of *this inside child::~child() is child, and not anything more derived. So when you have a further derived class class foo : child which overrides free(), then the overridden function will not be called.
There's nothing wrong with calling a virtual function from a constructor or destructor, base class or otherwise. But you have to know what it does: the dynamic type is the class being constructed or destroyed, so it won't call an override in a class derived from the one that's being constructed or destroyed. In particular, if the function is pure virtual, you won't get an override, and the behavior is undefined. So a good rule is "don't call pure virtual functions from constructors or destructors. In your example, class::free is not pure virtual, so there's no problem calling it.
This question already has answers here:
Do I need to explicitly call the base virtual destructor?
(7 answers)
Closed 7 years ago.
Please consider the following:
class base{
base();
~base();
}:
class derived : public base{
};
Does a base class destructor get automatically invoked when a derived object is destructed when the derived class has no destructor defined?
Otherwise, if I DO have a destructor in the derived class too, do I have to call the base class destructor explicitly?
class base{
base();
~base();
}:
class derived : public base{
derived();
~derived{
base::~base(); //do I need this?
}
};
The base class destructor is automatically invoked in this case; you do not need to call it.
However, note that when destroying an object through delete on a base class pointer and the destructor is not virtual, the result is going to be undefined behavior (although you might not get a crash).
Always declare the destructor as virtual in any class which is meant to be derived from. If the base class does not need to have a destructor, include a virtual one anyway with an empty body.
There is an exception to the above rule for an edge case: if your derived classes do not need to support polymorphic destruction, then the destructor does not need to be virtual. In this case it would be correct to make it protected instead; more details here, but be advised that this rarely occurs in practice.
Does a base class destructor is automatically invoked when a derived object is destructed and the derived class has no destructor defined?
Yes, the Base class destructor is automatically invoked after the Derived class Destructor, irrespective of Derived class destructor being explicitly defined or not.
Otherwise, if I have a destructor in the derived class too, do I need to call explicitly base class destructor too?
No, You don't need to.
There will not be any scenario in C++, where one has to explicitly invoke a destructor except while using placement new.
No, base destructors are invoked automatically in this case, in much the same way that base constructors are can be invoked automatically.
Note, though, that if you are using polymorphism and destroying through a base pointer, you should make sure that the destructor is virtual otherwise this will break.
You should never invoke a base class destructor from a derived class destructor.
The reason is base class destructor will be then called automatically for the second time and writing destructors in such way that this doesn't cause problem is problematic - see this question.