C++ 在堆上创建多态对象的数据成员向量?

C++ 在堆上创建多态对象的数据成员向量?,c++,vector,polymorphism,C++,Vector,Polymorphism,我有一个继承层次结构,其中A是抽象基类,B和C是多态子类 我希望在堆上有一个向量类数据成员,它可以包含B和C对象 所以在头文件中我有我的 vector<A*> polymorphicobjs; 向量多态性; 在构造器中,我试着做: polymorphicobjs = new vector<A>(); polymorphicobjs=newvector(); 但很明显,这是行不通的。如何实现这一点?为什么要执行新的 这一行: vector<A*> pol

我有一个继承层次结构,其中A是抽象基类,B和C是多态子类

我希望在堆上有一个向量类数据成员,它可以包含B和C对象

所以在头文件中我有我的

vector<A*> polymorphicobjs;
向量多态性;
在构造器中,我试着做:

polymorphicobjs = new vector<A>();
polymorphicobjs=newvector();

但很明显,这是行不通的。如何实现这一点?

为什么要执行新的

这一行:

vector<A*> polymorphicobjs;

如果确实要将其放入堆中,请将声明更改为:

vector<A*>* polymorphicobjs;
//        ^
vector*cobjs;
//        ^

但我认为没有必要…

您可以像使用任何其他类型一样实现这一点:

int i = new int; // Error
int *pi = new int; // works!
如果
vector
使您感到困惑,请尝试使用以下方法:

typedef vector<A*> vectorOfA;
vectorOfA v = new vectorOfA; // Error
...                          // guess what will work?
typedef向量向量a;
向量A v=新向量A;//错误
...                          // 猜猜怎么行?

所以问题是,你的多态cobjs是一个指针向量,而不是指向这样的向量的指针。

我真的建议你坚持使用标准的共享指针,如果C++11是一个选项,或者是boost的

您的基本问题是您声明了指针的
向量
,而不是指向
向量的指针

vector<T*> vec1;// a vector of pointers
vec1.push_back(new T); // add a pointer to our vector

vector<T*>* vec2; //a pointer to a vector of pointers
vec2 = new vector<T>; // create the vector on the heap
vec2->push_back(new T); // add pointer.
向量vec1;//指针向量 vec1.向后推(新T);//添加指向向量的指针 向量*vec2//指向指针向量的指针 vec2=新向量;//在堆上创建向量 vec2->推回(新T);//添加指针。 正如我所说,这很可能不是你想要的。你应该使用智能指针

vector<std::shared_ptr<A>> vec;
vec.push_back(std::make_shared<B>());
vec;
向量推回(std::make_shared());

您不需要新建向量。我怀疑你来自爪哇,那里的一切都需要一个新的。C++是不同的。只要在类中有一个
向量多态性cobjs
,就足以创建一个。无论如何,向量都会将其数据元素存储在堆上。如果愿意,可以在类的构造函数的初始化列表中调用它的构造函数。否则,它默认为空向量

要创建新对象并将其放入向量中,请执行以下操作:

polymorphicobjs.push_back(new B());
这将向向量添加一个新的B对象

您需要在某个时候删除它们(例如析构函数)

for(vector::iterator it=polymorphicobjs.begin(),end_it=polymorphicobjs.end();it!=end_it;++it)
{
删除*它;
}

智能指针向量会更好。

您不必担心保留原始指针的
std::vector
。在确保在正确的时间删除对象之后,这会给您带来很多麻烦。您应该做的是存储“托管”多态对象的容器(使用)。声明你的向量:

std::vector<std::unique_ptr<A>> polymorphicobjs;
这样,您就不必担心对向量中的对象调用
delete
。一旦你“放开”了向量(例如,当它超出了你函数的范围,或者如果它是一个类成员,它会被自动销毁),对象就会被删除。向量唯一地拥有对象

但我需要与其他代码共享对象

如果是这样,那么
std::unique\u ptr
就不是正确的选择。我们可以使用
std::shared\u ptr
表示对象是共享的:

std::vector<std::shared_ptr<A>> polymorphicobjs;
// [...]
polymorphicobjs.push_back(std::make_shared<B>());

我想我必须做些新的事情才能把向量放到堆上?@mezamorphic,因为你的向量已经初始化了。无需执行
新操作
。你为什么要把它堆起来?是否有特殊需要?即使向量不在堆上,它包含的对象也会在堆上(如果它们已在堆上分配)。我们可以预见problems@KevinCadieux这并没有改变事实,他想知道如何将向量本身放入堆中。你应该能够用
emplace
替换
push
,后者有可能避免不必要的副本。@下划线不一定正确
push_back
T&
重载,以对临时对象执行
move
。我的答案中的所有例子都是临时的。仅当类型不支持移动语义,但支持
std::unique_ptr
std::shared_ptr
do时,才会获得副本。此外,对于
std::shared_ptr
示例,
emplace
不知道调用
make_shared
。所以,你需要以缓存位置为代价创建一个副本。谢谢!我真的没有考虑这些细微差别。那么,在处理可移动类型和容器时,
push
emplace
之间是否有一个首选约定?我一直在假设应尽可能使用
emplace
(即使,例如对于
map
,这需要
分段构造的所有麻烦),但我可能过于简单化了(可能!)下划线d Scott Meyers在第42项中的“有效的现代C++”非常详细地谈到了这一点。最后,他建议你更喜欢安放而不是插入,这样你就不会走错路了。也就是说,一个(智能)指针容器需要一个“裸”的
new
或移动一个
make_
智能指针来使用定位。但是,在这种情况下,这并不比插入快。因此,无论何时从容器外部创建类型(出于某种原因),我都更喜欢插入而不是放置。在我上面的回答中,这有利于
向后推
而不是
向后放置
std::vector<std::unique_ptr<A>> polymorphicobjs;
polymorphicobjs.push_back(std::unique_ptr<B>(new B));
std::vector<std::shared_ptr<A>> polymorphicobjs;
// [...]
polymorphicobjs.push_back(std::make_shared<B>());
// C++14
std::vector<std::unique_ptr<A>> polymorphicobjs;
// [...]
polymorphicobjs.push_back(std::make_unique<B>());