Home > Software engineering >  shared_ptr to derived class from a specific base class
shared_ptr to derived class from a specific base class

Time:09-02

I feel like this is a pretty basic C question. I am trying to make a class which contains a member variable which is a shared_ptr to any class which is derived from a specific interface, but does not care which particular derived class it is. I am implementing it as follows:


class Base
{
public:
  Base();
  virtual void do_stuff() = 0;
};

class Derived : Base {
  Derived() {}
  void do_stuff() { };
};


class Foo
{

public:
  Foo() {
    mPtr = std::make_shared<Derived>();
  }

protected:
  std::shared_ptr<Base> mPtr;
};

Compiling gives the following error at the top:

error: no match for ‘operator=’ (operand types are ‘std::shared_ptr<Base>’ and ‘std::shared_ptr<Derived>’)
     mPtr = std::make_shared<Derived>();

What's the proper way to do this?

Edit: Changing inheritence from Base to public Base made it work. However, trying to instantiate the class makes the linker break.


Foo foo;

Compiling gives

libfoo.so: undefined reference to `Base::Base()'
collect2: error: ld returned 1 exit status

What's this about?

CodePudding user response:

Fixed the access specifiers and more:

#include <memory>

class Base {
public:
    Base() = default;            // must have implementation

    // virtual dtor - not strictly needed for shared_ptr:
    virtual ~Base() = default;
    virtual void do_stuff() = 0;
};

class Derived : public Base {    // public inheritance
public:                          // public access
    // Derived() {}              // not needed
    void do_stuff() override {}; // mark override 
};

class Foo {
public:
    Foo() :
        mPtr{std::make_shared<Derived>()} // use the member init-list
    {}

private:                         // prefer private member variables
    std::shared_ptr<Base> mPtr;
};

CodePudding user response:

Derived should use public inheritance, rather than private inheritance, and Derived() should be public.

class Derived : public Base 
{
public:
   Derived() {}
   void do_stuff() override{ };
};
  • Related