C++ 在堆上创建多态对象的数据成员向量?
我有一个继承层次结构,其中A是抽象基类,B和C是多态子类 我希望在堆上有一个向量类数据成员,它可以包含B和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
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>());