Using Derived class with std :: shared_ptr base class

Is the following approach good?

class TA { }; class TB : TA { }; std::shared_ptr<TA> spta; spta.reset(new TB); 
+5
source share
3 answers

There is one problem with the code shown, TB must be inherited publicly from TA . You have shared_ptr<TA> , so the pointer that you want to save in it must be converted to TA , but with private inheritance, the database is not available, so your code will not compile.

 class TA { }; class TB : public TA { }; 

In addition, the code has no errors and behaves well. Usually, when you do a polymorphic deletion of an instance of a derived class using the base class pointer, you need the base class destructor to be virtual , so the derived class destructor is called, but this is not necessary with shared_ptr . shared_ptr::reset is a function template that will accept any Y* that can be converted to a type of managed pointer. The same is true for the shared_ptr constructor template .

In this case, you should prefer to make the base class destructor virtual , especially if the classes involved have other virtual functions.

+3
source

No, this is not for TA is closed.

Also, as suggested in the comments, the base class destructor must be virtual. This is usually good practice, as you cannot guarantee that instances of your classes will be used only with shared pointers.

For it to work, you must at least change the following lines:

 class TA { }; class TB : TA { }; 

Properly:

 class TA { virtual ~TA() { } }; class TB : public TA { }; 

Those that are good as the following example are good:

 class TA { virtual ~TA() { } }; class TB : public TA { }; TA *spta = nullptr; spta = new TB; 

It basically depends on what good remedies are for you. It is legal, at least.

+2
source

This is not an answer to the question, it is an attempt to eliminate any confusion that shared_ptr would seem to have a magical ability to avoid using a virtual destructor.

Here is a small demo program:

 #include <iostream> #include <memory> struct A { ~A() { std::cout << __func__ << std::endl; } void foo() { do_foo(); } protected: virtual void do_foo() { std::cout << "A::" << __func__ << std::endl; } }; struct B : A { ~B() { std::cout << __func__ << std::endl; } virtual void do_foo() override { std::cout << "B::" << __func__ << " "; A::do_foo(); } }; using namespace std; auto main() -> int { std::shared_ptr<A> p = std::make_shared<A>(); p->foo(); p = std::make_unique<B>(); p->foo(); cout << "deleting B:" << endl; return 0; } 

expected output:

 A::do_foo ~A B::do_foo A::do_foo deleting B: ~B ~A 

Note that the correct destructor is called when B was destroyed at the end of main ().

0
source

Source: https://habr.com/ru/post/1236569/


All Articles