tags:

views:

128

answers:

5

Hello everyone, let's assume I have two classe

class Base{};

class Derived: public Base{};

none has d'tor, in this case if I declare about variables:

Base b;
Derived d;

my compiler will produce for me d'tors, my question is, the default d'tors of the b and d will be virtual or not?

+8  A: 

my question is, the d'tors of the b and d will be virtual or not

Short answer : Nopes!

Prasoon Saurav
+3  A: 

They will NOT be virtual.However, if you declared(and defined) a virtual dtor in Base, then the derived's dtor would be automatically virtual. HTH.

Armen Tsirunyan
+4  A: 

my question is, the d'tors of the b and d will be virtual or not

No, they won't. If you want a virtual destructor, you will have to define your own, even if its implementation is exactly the same as that which would be supplied by the compiler:

class Base {
  public:
    virtual ~Base() {}
};
sbi
A: 

The destructors of Base and Derived will not be virtual. To make a virtual destructor you need to mark it up explicitly:

struct Base
{
    virtual ~Base() {}
};

Actually there's now only one reason to use virtual destructors. That is to shut up the gcc warning: "class 'Base' has virtual functions but non-virtual destructor". As long as you always store your allocated objects in a shared_ptr, then you really don't need a virtual destructor. Here's how:

#include <iostream>   // cout, endl
#include <memory>     // shared_ptr
#include <string>     // string

struct Base
{
   virtual std::string GetName() const = 0;
};

class Concrete : public Base
{
   std::string GetName() const
   {
      return "Concrete";
   }
};

int main()
{
   std::shared_ptr<Base> b(new Concrete);
   std::cout << b->GetName() << std::endl;
}

The shared_ptr will clean up correctly, without the need for a virtual destructor. Remember, you will need to use the shared_ptr though!

Good luck!

Daniel Lidström
@Daniel: Really? Will the shared_ptr clean up correctly? Could you please in this case demonstrate how that effect could be implemented?
Armen Tsirunyan
@Armen: The shared_ptr uses its own destructor to delete the Concrete instance. This is known as RAII within the C++ community. My advice is that you learn all you can about RAII. It will make your C++ coding so much easier when you use RAII in all situations.
Daniel Lidström
@Daniel: I know about RAII, and I also know that eventually the shared_ptr destructor may delete the stored px when pn reaches 0. But if px had static type pointer to Base and dynamic type pointer to Derived, then unless Base has a virtual destructor, this will result in undefined behavior. Correct me if I am wrong.
Armen Tsirunyan
@Daniel: Even with RAII, at some low level of your design, there will be classes (i.e. those that directly wrap the resources) that must do explicit cleanup upon destruction.
Oli Charlesworth
@Armen: The shared_ptr knows the static type is Concrete. It knows this since I passed it in its constructor! Seems a bit like magic, but I can assure you it is by design and extremely nice.
Daniel Lidström
@Oli: When you apply RAII recursively, always using shared_ptr, the effect is that suddenly you don't really need a destructor at all! shared_ptr's can wrap any resource and it is even more convenient when you can specify the custom deleter using the new lambda syntax.
Daniel Lidström
@Daniel: Right, but whatever lives at the end of your "recursion" must explicitly do clear-up that might be more than just memory deallocation (imagine a database-connection class, or a file I/O class).
Oli Charlesworth
@Daniel, @Oli: OK, I made a new topic on this issue, let's discuss there :)
Armen Tsirunyan
@Daniel: your example won't work because you use a `std::shared_ptr<Base>` which wants a `Base*` for its constructor, so it won't know that its internal object is in fact a `Concrete`. However this code will work: `std::shared_ptr<Base> b = std::shared_ptr<Concrete>(new Concrete)`
Tomaka17
@Tomaka17: A pointer to Concrete is convertible to a pointer to Base. That's why it works.
Daniel Lidström
@Oli: A custom deleter can handle any type of clean-up.
Daniel Lidström
I think that it's poor advice to imply that polymorhphic base classes should have virtual destructors only to silence a warning. Not providing a virtual destructor for a class designed to be a common base class for an inheritance hierarchy forces the user to use `shared_ptr` or equivalent. Classes that don't attempt to manage how they are used are more versatile. Giving such a class a virtual destructor allows it to be used correctly in more situations at little extra cost. A user would typically get no warning about incorrect use in this case. Classes should be made easy to use correctly.
Charles Bailey
@Charles: You are right. As I have no way to oversee the OP's work I can't know he follows the requirements. So my advice was not really appropriate for a beginner. If he was working with me though, I would lead him on to the path of design patterns. Any interface hierarchy would need the use of an abstract factory. However, that's a discussion I don't want to have here.
Daniel Lidström
@Daniel: I think you don't understand the problem. If you call the constructor of `std::shared_ptr<Base>` by giving it a `Base*` pointer (converted from a `Concrete*` pointer), the shared_ptr will call the destructor of Base, but the destructor of Concrete won't be called. This is because it is not possible for the shared_ptr to know that this is a Concrete object.
Tomaka17
The best way to safely build a shared_ptr is to use `std::make_shared<Concrete>(...parameters for Concrete's constructor...)`
Tomaka17
@Tomaka17: You are correct that `Base* pBase = new Concrete; shared_ptr<Base> shpBase(pBase);` is dangerous but that's part of Daniel's point. All he was saying is that `shared_ptr<Base> shpBase(new Concrete);` is not dangerous, which it isn't, because of `shared_ptr`'s constructor template.
Charles Bailey
@Charles: I just checked and you're right. This used to be dangerous in boost, and I didn't know they changed it.
Tomaka17
+1  A: 

How can they be virtual unless you explicitly make them as virtual

CadetNumber1
@downvoter reason please?
CadetNumber1