Pure virtual and std::shared_ptr
Asked Answered
W

3

6

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?

Writeoff answered 11/4, 2014 at 12:30 Comment(3)
The default constructor initializer is incorrect, and simply should not be there. std::shared_ptr<> like any pointer, can contain nullptr, and will do so with default construction.Rhodos
where is virtual destructor for base?Rockabilly
@Rockabilly Good point, but not required for shared_ptr.Biddy
S
8

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.

Saharanpur answered 11/4, 2014 at 12:35 Comment(2)
Yeah ... obviously I need a coffee :) Thanks!Writeoff
or simply Container() {}Rhodos
C
2

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) {}
Coston answered 11/4, 2014 at 12:36 Comment(0)
C
0

Use a templated constructor for directly constructing the object.
So, you cannot have a default constructor unless

  • B gets non-abstract,
  • you decide for one concrete favored derived class or
  • you accept 0-initialising m_x.
Cassaundra answered 11/4, 2014 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.