我遇到一个问题,即指针向量似乎没有按照我预期的多态方式运行。陌生人的事实是它适用于它所指向的每一个其他对象。
shotgunNodes
和rifleNodes
都包含两个整数,它们代表一个级别中的适当位置,用于放置我正在生成的拾取器。
pickups
是kpointers(父类)的向量,ShotgunPU
和RiflePU
是派生类。我将在下面发布标题和来源。
奇怪的问题是,如果我打破代码,一次一个循环,一切似乎都很顺利。第一个枪指针设置为指向步枪物体。精细。然后将下一个枪指针设置为指向下一个步枪对象,此时出于某种奇怪的原因,向量中的前一个指针应该指向第一个步枪被切断,现在只指向步枪的枪部分对象,所以我失去了它的所有派生功能。
在循环结束时,我有一个指向枪步枪霰弹枪的枪矢,它应该是步枪步枪霰弹枪。
int j = 0;
for (vec_i_sz i = 0; i < rifleNodes.size(); i++, j++)
{
riflePickups.push_back(RiflePU(agents, mesh));
riflePickups[i].Position(nodes[rifleNodes[i]].Position());
pickups.push_back(&riflePickups[i]);//point the pickup pointer to the rifle pickup
pickups[j]->Index(j);
pickups[j]->NodeIndex(rifleNodes[i]);
}
for (vec_i_sz i = 0; i < shotgunNodes.size(); i++, j++)
{
shotgunPickups.push_back(ShotgunPU(agents, mesh));
shotgunPickups[i].Position(nodes[shotgunNodes[i]].Position());
pickups.push_back(&shotgunPickups[i]);
pickups[j]->Index(j);
pickups[j]->NodeIndex(shotgunNodes[i]);
}
可能还值得注意的是,此代码(显然是翻译版本,但在相同的结构中)适用于程序的C#版本。所以我怀疑这是代码的结构。有什么我不知道指针的工作方式吗?
这是在使用它们的标题中声明向量的方式:
std::vector<Pickup*> pickups;
std::vector<RiflePU> riflePickups;
std::vector<ShotgunPU> shotgunPickups;
我刚刚注意到写了这个,它们在循环运行之前(在构造函数的主体中)实际上并没有在初始化列表中初始化,但是这不应该是正确的,因为它们是类类型吗?
如果它们在列表中初始化,它仍然会发生。
pickups(std::vector<Pickup*>()),
riflePickups(std::vector<RiflePU>()),
shotgunPickups(std::vector<ShotgunPU>())
答案 0 :(得分:1)
当向向量添加项时,push_back
可以在需要调整其底层缓冲区大小时使所有指向容器的指针无效。每次发生这种情况时,您已经存储在pick_ups
中的指针都会变成垃圾。
1)您可以预先reserve
和riflePickups
中的所有项目shotgunPickups
内存。这将确保在添加许多项目时不会调整这些向量的大小,并且项目的地址将保持不变。
2)您可以在{/ 1}} 之后将指针存储在之后,您已在两个向量中创建了所有项目,而不是在这些向量尚未达到其最终大小时。
3)您可以使用pick_ups
覆盖std::list
和riflePickups
的向量。在列表中,只有在删除了所述项目时,指向项目的指针才会失效。
最终,你真的需要这个吗?也许你可以只在一个向量中存储(最好是智能的)指向动态分配对象的指针。
答案 1 :(得分:0)
&#34;访问者&#34;已经解释了会发生什么,并且正如他提示的那样,我认为你的基本问题是当你应该使用指向对象的指针时使用对象。请记住,C#(和Java)确实使用指向所有对象的指针,即使它在语法中不明显。所以这个C#代码:
Person daisy = new Person();
daisy.salary = 39000;
dosomethingwith(daisy);
也会编译为C ++,如果你只删除关键字 new ,执行它时会发生什么更接近这个C ++代码:
Person* daisy = new Person();
daisy->salary = 39000;
dosomethingwith(daisy);
Java和C#程序员通常会错误地转移到C ++,他们使用 new 创建所有对象,但也许情况恰恰相反。