我需要将派生类的元素添加到抽象类的共享指针列表中。
我一直在尝试这个。我知道我正在尝试在下面的示例中创建抽象类的实例,但我不知道如何使其工作。
简化的类如下所示:
using namespace std;
class Abstract
{
public:
virtual string toString() const = 0;
};
class A : public Abstract
{
public:
A(int a, int b) : a(a), b(b)
{}
string toString() const { return "A"; }
private:
int a;
int b;
};
class B : public Abstract
{
public:
B(int b) : b(b)
{}
string toString() const { return "B"; }
private:
int b;
};
问题出在以下类中:
class Data
{
public:
Data(const string & name) : name (name)
{}
Data AddData ( const Abstract & a )
{
//Need to fix next line
l1.push_back(make_shared<Abstract>(a));
return (*this);
}
private:
list<shared_ptr<Abstract>> l1;
string name;
};
我想避免RTII和dynamic_cast。我对不同的解决方案持开放态度。我只需要以某种方式将不同类型的元素存储到单个容器中。
我需要像这样使用类数据:
Data test("Random Name");
test.AddData(A(1,2))
.AddData(B(3))
.AddData(B(4));
最佳答案
有什么问题吗?
问题是 make_shared<X>
将通过调用 X
的构造函数来创建共享对象。在你的情况下这是不可能的,因为它是一个抽象类型。所以它甚至无法编译。
如果X
不会是抽象的,它会编译并且看起来可以工作。但这会导致创建一个 sliced共享对象。
如何解决?
您需要本着 prototype design pattern 的精神使用虚拟克隆功能:
class Abstract
{
public:
virtual string toString() const = 0;
virtual shared_ptr<Abstract> clone() const= 0;
};
您必须在派生类中重写它,例如:
class B : public Abstract
{
public:
...
shared_ptr<Abstract> clone() const override { return make_shared<B>(*this); }
...
};
然后您可以利用多态性来填充列表:
Data& AddData ( const Abstract & a ) // return preferably a reference
{
//Need to fix next line
l1.push_back(a.clone());
return (*this);
}
补充说明
如果您擅长method chaining ,我想你会想要 AddData()
返回一个引用。如果没有,那么每次您都会调用 AddData()
,您将创建 Data
的拷贝,这会创建大量不必要的拷贝。
关于c++ - 如何向列表添加值<shared_ptr<Abstract>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55879042/