我有以下结构:
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(){}
}
并使用std::shared_ptr<A>
作为我工厂的返回类型。
std::shared_prt<A> Factory::get(params...)
{
...
return std::make_shared<B>(params);
}
std::shared_ptr<A> Aptr = Factory::get(params...)
现在我尝试将其传递给外部方法:
boost::iostreams::filtering_istream
void push( const T& t,
std::streamsize buffer_size = default value,
std::streamsize pback_size = default value );
此调用在编译时失败,因为some_external_function尝试调用A的纯member()
而不是B。
concept_adapter.hpp:122:错误:无法将字段'boost :: iostreams :: detail :: concept_adapter :: t_'声明为抽象类型'A'
答案 0 :(得分:2)
你 在这里使用PImpl成语。
push
方法要求第一个参数是可复制构造的。这意味着它被复制到Boost的内部深处。没有好处,因为你不能复制多态对象,它会被切片。
解决方案是拥有一个非多态类APimpl
,它将指针(共享,唯一或原始,您决定)保存到A
,并转发对该指针的调用。它可以自由复制,不会产生切片效果。
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;
};
您可能需要在clone
中使用A
方法并在复制APimpl
时使用该方法,或者在A
的多个实例之间共享APimpl
。你想要哪一个取决于A
的作用。我的例子演示了第二种情况。