我正在制作小型模拟应用程序,其基类名为Entity,子类名为Herbivore和Carnivore。由于我使用SFML,我需要更新它们,处理交互等等。我的第一个想法是将它们存储在两个不同的向量中,但我认为这不是最有效的解决方案。
然后我尝试使用一点点多态性,但这里是我彻底失败的地方。我有一个指向Entity对象的指针向量。这是它的声明:
std::vector<Entity*> entityVector;
在创建新对象时,我从不同的类调用函数:
void ObjectFactory::createHerbivore(Sprite sprite, Vector2f position,
std::vector<Entity*> *vector)
{
Herbivore herbivore(sprite, position, m_GameResolution);
Entity* p_herbivore = &herbivore;
vector->push_back(p_herbivore);
}
以下是我在主Game类中调用该函数的方法:
//Creating new herbivore objects
if (inputEvent.key.code == Keyboard::H)
{
srand((int)time(0) * dt.asMilliseconds() + 1 * 800 * entityVector.size() + 5);
herbivorePosition.x = rand() % (int)videoResolution.x;
herbivorePosition.y = rand() % (int)videoResolution.y;
factory.createHerbivore(herbivoreSprite, herbivorePosition, &entityVector);
(entityVector.back())->setDangerSprite(dangerSprite);
}
然后我继续研究那个向量,或者至少尝试一下,但是第一次尝试读取保存在该指针下的数据时崩溃了。当然,通过痛苦而漫长的调试过程我已经意识到,我在这里创建了一个新对象,传递了它的地址然后通过离开这个函数来销毁它。所以我的问题是:如何处理它,所以我可以保留所有这些甜的多态性?
答案 0 :(得分:2)
“我意识到,我在这里创建了一个新对象,传递了它的地址,然后通过离开这个函数来销毁它。所以我的问题是:如何处理它,所以我可以保留所有这些甜的多态性?
您可以拥有shared_ptr<Entity>
的向量,并且可以使用make_shared<Herbivore>(sprite, position, m_GameResolution)
之类的代码创建一个新的动态分配对象。
shared_ptr
而不是像Entity*
这样的原始指针基本上可以用来清理。当没有更多shared_ptr
个引用该对象时,它会被自动销毁并释放内存。我们说shared_ptr
的集合指的是拥有。
make_shared<Herbivore>
代替例如shared_ptr<Entity>{ new Herbivore{ sprite, position, m_GameResolution } }
避免了后者的一些低效(额外的动态分配),并且还可以帮助避免未定义的行为,其中您在函数调用中创建两个或更多这样的对象作为实际参数。
示例:
#include <iostream>
#include <typeinfo> // for typeid
#include <memory>
#include <vector>
using namespace std;
struct Entity { virtual ~Entity(){} };
struct Herbivore: Entity {};
struct Carnivore: Entity {};
auto main() -> int
{
vector<shared_ptr<Entity>> entities;
entities.push_back( make_shared<Herbivore>() );
entities.push_back( make_shared<Herbivore>() );
entities.push_back( make_shared<Carnivore>() );
entities.push_back( make_shared<Herbivore>() );
for( auto p: entities )
{
cout << typeid( *p ).name() << endl;
}
}