Do I need virtual destructor when I am using boost::ublas matrix ?
By the way, my class is a template class.
Do you mean you have this?
template <typename Whatever>
struct my_class
{
// ...
boost::ublas::matrix m;
};
There's nothing here that dictates you have a virtual destructor.
You want a virtual destructor when you intend on having users publically derive from your class. So that question should be "Users will publically derive from my class, do I need a virtual destructor?". Yes, you do.
The reason is that doing this leads to undefined behavior:
struct base {}; // no virtual destructor
struct derived : base {};
base* b = new derived;
// undefined behavior, dynamic type does not match static type,
// and the base class does not have a virtual destructor
delete b;
This does not:
struct base { virtual ~base(){} }; // virtual destructor
struct derived : base {};
base* b = new derived;
// well-defined behavior, dynamic type does not match static type,
// but the base class has a virtual destructor
delete b;
Note that it has nothing to do with what members there are in the base class. You always need a virtual destructor if users will be deleting derived classes through a pointer to a base class.
I would recommend you get a book so you know what it does, because it sounds like you just throw things around and hope it works, which isn't a very good approach.
Related
Are destructors required to be virtual when implementing curiously recurring template pattern (CRTP)? And if not, what is the proper non-virtual implementation?
I'll provide an example to hopefully make things easier:
template<typename T>
class Base
{
public:
virtual ~Base()
{
// Should this be virtual? Non-virtual?
std::cout << "Base::~Base()\n";
}
};
class Derived : public Base<Derived>
{
public:
~Derived() override
{
std::cout << "Derived::~Derived()\n";
}
};
int main()
{
Base<Derived>* b = new Derived;
delete b;
}
Result:
Derived::~Derived()
Base::~Base()
(Live Sample Here)
EDIT: Updated the example to use runtime polymorphism so that the virtual destructor is required for proper cleanup.
A CRTP base class is no different from any other base class in this sense. You will need a virtual destructor only if you are going to delete an object of type Derived via a pointer to Base<Derived>. Otherwise, a virtual destructor is not required.
Base<Derived>* b = new Derived;
delete b; // Base<Derived>::~Base<Derived> must be virtual
In the example you showed, a virtual destructor is not needed. A virtual destructor is just needed when you may need to call it using a pointer to the base class, the same as an overriden function must be virtual in this case. And in the case of a CRTP class like you showed, there is rarely a need to delete a Base<T> instead of T itself.
int main()
{
Derived *a = new Derived();
// we have the right type anyway, so dont actually need a virtual anything (even normal virtual methods)
delete a;
Derived *a = new Dervied();
Base<Derived> *b = a;
// We are now deleting via a parent class, so this needs a virtual destructor.
// This is pretty uncommon with a simple CRTP however.
delete b;
}
If you're going to call delete on a pointer of a base class that's pointing to a derived object then you need a virtual destructor, that's all there is to it. CRTP or no CRTP.
Given this program:
struct Base
{
virtual void f() {}
};
struct Derived:public Base
{
};
int main()
{
Derived* c = new Derived;
delete c;
}
gcc-4.4 -Wall is fine but gcc-5.2 -Wall gives warning: deleting object of polymorphic class type 'Derived' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]
I saw the discussion on deleting a base pointer but in my case it's the derived object. I think it's a gcc bug, but apparently GNU doesn't think so. Is there anyway to get rid of the warning without changing the base class definition?
GCC has every right to emit that warning. Why? Because unless you declare that Derived is final, it's entirely possible for someone to create a MoreDerived type that is derived from Derived. At which point, your deletion of a Derived pointer can very much be invalid.
Adding a virtual destructor to Base has no real downsides. Yes, the destructor will be a virtual call. But that's hardly going to be a performance bottleneck.
Adding virtual ~Base() {} to Base would fix the warning.
So would adding final to Derived.
class Derived final : public Base
{
...
};
And so would adding a virtual destructor to Derived.
class Derived : public Base
{
public:
virtual ~Derived() {}
...
};
Also, if you don't plan on using Derived polymorphically, you could inherit it privately. This doesn't prevent the warning, but you could never assign a Derived pointer to a Base pointer, and thus could never delete a Derived via a Base pointer.
class Derived : private Base
{
...
};
The C++ Standard, [expr.delete], paragraph 3 [ISO/IEC 14882-2014], states the following:
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
Do not delete an object of derived class type through a pointer to its base class type that has a non-virtual destructor. Instead, the base class should be defined with a virtual destructor. Deleting an object through a pointer to a type without a virtual destructor results in undefined behavior.
In this compliant solution, the destructor for Base has an explicitly declared virtual destructor, ensuring that the polymorphic delete operation results in well-defined behavior.
struct Base {
virtual ~Base() = default;
virtual void f();
};
struct Derived : Base {};
void f() {
Base *b = new Derived();
// ...
delete b;
}
You can find more information, if use this link: https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP52-CPP.+Do+not+delete+a+polymorphic+object+without+a+virtual+destructor
I've had some second thoughts on multiple virtual destructors, esp. after reading reading http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx .
Suppose I have
class Base
{
public:
Base();
virtual ~Base();
private:
Logger* _logger;
};
//and
class Derived : public Base{
public:
Derived();
virtual ~Derived();
private:
Logger* _logger;
};
in the cpp files, in each destructor I am deleting the respective _logger pointers
Base::~Base(){ //base.cpp
delete _logger;
}
Derived::~Derived(){ //derived.cpp
delete _logger;
}
will this work as I intended, without memory leaks?
First off, if you make the base class destructor virtual, all derived classes will automatically get a virtual destructor if you declare them as virtual or not. This is generally true for matching signatures: if a base class has a virtual function with the same signature as a function in a derived class, the function in the derived class is an override and is virtual (although in C++ 2011 you can prevent further overriding using the final keyword in which case another override would create an error).
That said, destructors are special: when you make a destructor virtual it will still be called even if there is another overriding destructor! The only impact of a destructor being virtual is what happens if you delete an object using a pointer to a base class when the object actually happens to be of a derived type: If the destructor isn't virtual you get undefined behavior while the Right Thing happens if the destructor is virtual. For example:
class not_a_base {};
class bad_idea: public not_a_base {};
class a_base { public: virtual ~a_base() {} };
class ok: public a_base {};
int main() {
a_base* ab = new ok;
delete ab; // <---- all is good here!
not_a_base* nab = new bad_idea;
delete nab; // <---- results in undefined behavior
}
The reason destructors are not virtual by default is simply that this would mean that object size is always increased by a word size which is unacceptable in general.
Base::_logger is a different variable then Derived::_logger. So you should delete Derived::_logger in Derived's dctor, or else you leak memory.
Note that this has nothing to with it being private. Consider this example program:
#include <iostream>
class A {
public:
bool foo;
};
class B: public A {
public:
bool foo;
};
int main()
{
B b;
std::cout << &b.B::foo << ' ' << &b.A::foo << '\n';
}
The addresses are different. That means they're different variables, even though they have the same name. This is possible since each class introduces its own namespace, so the names don't really clash. The first is A::foo, the other one B::foo.
Since your destructors are virtual, both will get called, and the correct _logger will be deleted in both of them.
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
Suppose I have this code
class Base{
public:
int getVal();
private:
int a, b;
};
class Derived::public Base{
public:
void printVal();
};
int main(){
Base *b = new Derived();
delete b;
}
I know a virtual destructor would delete things properly, but is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class? What will happen if this is done?
Is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class?
Yes.
The behavior is undefined regardless the contents of the derived class.
What will happen if this is done?
Anything could happen.
For primitive-type data, your example will most likely work in practice. As a matter of fact, incurring a vtable could actually hinder performance (so there may be some legitimate use here), but it is technically undefined, per 5.3-5.4:
If the static type of the operand [of
the delete operator] is different from
its dynamic type, the static type
shall be a base class of the operand's
dynamic type and the static type shall
have a virtual destructor or the
behaviour is undefined.
It really all depends on the "heapness" of the data in your class, and as there are no heap-allocated members (in your case), you should be fine, but it's definitely a code smell.
The virtual desctructor in the derived class is needed in order to properly call the derived destructor (polymorphism), when the derived object is created through a pointer to the base class.
High Integrity CPP Rule 3.3.2 Write a 'virtual' destructor for base classes. (QACPP 2116)
Justification: If an object will ever be destroyed through a pointer to its base class, then that base class should have a virtual destructor. If the base class destructor is not virtual, only the destructor for the base class will be invoked. In most cases, destructors should be virtual, because maintenance or reuse may add derived classes that require a virtual destructor.
class Base {};
class Derived : public Base { public: ~Derived() {} };
void foo() {
Derived* d = new Derived; delete d; // correctly calls derived destructor
}
void boo() {
Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor!
}