Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure virtual and std::shared_ptr

Possibly I just missed something from the documentation (or just can't do a proper Google serach), but I have issues with a shared_ptr and pure virtual functions.

So a short example which works:

class Base
{
public:
    virtual int stuff() = 0;
};

class Derived : public Base
{
public:
    virtual int stuff() {return 6;}
};

class Container
{
public:
    Container() : m_x( 0 ) {}
    Container(Base* x) : m_x(x) {} 

private:
    Base* m_x;
};

and since I'd like to use the new fancy std::shared_ptr I modify the Container to be:

class Container
{
public:
    Container() : m_x( std::make_shared<Base>() ) {}
    Container(const std::shared_ptr<Base>& x) : m_x(x) {} 

private:
    std::shared_ptr<Base> m_x;
};

Obviously, this does not work, clang and other compilers complain, that: error: allocating an object of abstract class type 'Base' in the Container() : m_x( std::make_shared<Base>() ) {} line.

So, the question: How to make this work with std::shared_ptr?

like image 950
Ferenc Deak Avatar asked Mar 20 '23 22:03

Ferenc Deak


2 Answers

Your Problem is here:

Container() : m_x( std::make_shared<Base>() ) {}

You cannot create an object of Base. What you want is an empty shared_ptr. So do this.

Container() : m_x( std::shared_ptr<Base>() ) {}

or do this.

Container() : m_x() {}

Which is equal.

like image 126
mkaes Avatar answered Mar 22 '23 11:03

mkaes


std::make_shared<Base>() is equivalent to new Base(). What you want is either completely omit m_x initialization(which will be initialized empty by default constructor) or do it explicitly:

Container() : m_x(nullptr) {}
like image 23
projedi Avatar answered Mar 22 '23 13:03

projedi