Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ use derived class in std::shared_ptr<baseclass>

I have the following structure:

class A 
{
   A(const A&) {...}
   virtual int member() = 0;
   virtual ~A() {}; 
}

class B : public A 
{ 
   virtual int member(){... }  
   virtual ~B(){}
}

class C : public A 
{
   virtual int member(){... }  
   virtual ~C(){}
} 

And use std::shared_ptr<A> as return type of my factory.

std::shared_prt<A> Factory::get(params...)
{
   ...

   return std::make_shared<B>(params);
}

std::shared_ptr<A> Aptr = Factory::get(params...) 

Now I try to pass it to an external method:

boost::iostreams::filtering_istream

void push( const T& t,
           std::streamsize buffer_size = default value,
           std::streamsize pback_size = default value );

this call fails at compile time because some_external_function tries to call the pure member() of A and not of B.

concept_adapter.hpp:122: Error:cannot declare field 'boost::iostreams::detail::concept_adapter::t_' to be of abstract type 'A'

like image 334
Steve Avatar asked Jun 07 '26 04:06

Steve


1 Answers

You have to use the PImpl idiom here.

The push method requires that the first argument is copy constructible. Which means that it is copied somewhere deep inside the guts of Boost. No good, because you cannot copy a polymorphic object, it will be sliced.

The solution is to have a non-polymorphic class APimpl that holds a pointer (shared, unique or raw, you decide) to A, and forwards calls to that pointer. It can be copied freely with no ill effects of slicing.

class APimpl
{
   public:
     APimpl(std::shared_ptr<A> a) : p_a(a) {}
     // compiler-generated copy ctor and assignment are OK here
     void method() { p_a->method(); }
   private:
     std::shared_ptr<A> p_a; 
};

You may need to have a clone method in A and use it when copying APimpl, or have an A shared between many instances of APimpl. Which one you want depends on what A does. My example demonstrates the second case.

like image 61
n. 1.8e9-where's-my-share m. Avatar answered Jun 10 '26 09:06

n. 1.8e9-where's-my-share m.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!