我需要将派生类的元素添加到抽象类的共享指针列表中。
我一直在尝试。我知道我在下面的示例中尝试创建抽象类的实例,但是我不知道如何使它起作用。
简化的类如下:
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));
答案 0 :(得分:2)
问题在于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
的副本,这将创建很多不必要的副本。
答案 1 :(得分:0)
您不能将抽象类实例推送到列表中。我要么重载了AddData()函数,要么使用了模板。
class Data
{
public:
Data(const string & name) : name (name) {}
Data& AddData (const A &a)
{
l1.push_back(make_shared<A>(a));
return (*this);
}
Data& AddData (const B &b)
{
l1.push_back(make_shared<B>(b));
return (*this);
}
private:
list<shared_ptr<Abstract>> l1;
string name;
};
或
class Data
{
public:
Data(const string & name) : name (name) {}
template<typename T>
Data& AddData (const T &a)
{
l1.push_back(make_shared<T>(a));
return (*this);
}
private:
list<shared_ptr<Abstract>> l1;
string name;
};