Я хочу, чтобы ссылки на созданные объекты автоматически добавлялись в вектор (часто несколько векторов) при создании объектов. Чтобы придать некоторый контекст, этот код будет использоваться в игре для наборов игровых объектов (Drawable, Collidable, Enemies и т. Д.), Следовательно, потребуется несколько векторов.
Пример того, чего я пытаюсь достичь, показан здесь:
#include <iostream>
#include <memory>
#include <vector>
class BaseClass :public std::enable_shared_from_this<BaseClass>
{ //for example "drawable"
public:
BaseClass()
{
std::cout << "Base Created"<<std::endl;
BaseList.push_back(shared_from_this());//I want to put a reference to this object in a vector
}
~BaseClass()
{
std::cout << "Base Deleted"<<std::endl;
}
static std::vector<std::shared_ptr<BaseClass>> BaseList;
};
class DerivedClass :public BaseClass
{//for example "enemy"
public:
static std::vector<std::shared_ptr<BaseClass>> DerivedList; //shared_ptr of baseclass can point to derivedclass
DerivedClass()
{
std::cout << "Derived Created" << std::endl;
DerivedList.push_back(shared_from_this());//reference to this object in a vector in addition to the other vector
}
~DerivedClass()
{
std::cout << "Derived Deleted" << std::endl;
}
};
std::vector<std::shared_ptr<BaseClass>> BaseClass::BaseList;
std::vector<std::shared_ptr<BaseClass>> DerivedClass::DerivedList;
int main()
{
std::shared_ptr<BaseClass> C = std::make_shared<BaseClass>();
std::shared_ptr<BaseClass> D = std::make_shared<DerivedClass>();
BaseClass::BaseList.clear(); //C should be deleted, D should not since it is still in DerivedList
DerivedClass::DerivedList.clear(); //now D should be deleted
return 0;
}
В этом коде использование shared_from_this()
работает неправильно, поскольку оно находится в конструкторе ( Как показано здесь ). Ранее я преодолел эту проблему с помощью отдельных статических функций, например:
void BaseClass::makeOne()
{
std::shared_ptr<BaseClass> P(new BaseClass());
BaseClass::BaseList.push_back(P);
}
void DerivedClass::makeOne()
{
std::shared_ptr<BaseClass> P(new DerivedClass());
BaseList.push_back(P);
DerivedList.push_back(P);
}
однако в контексте, где несколько классов получены из одного базового класса, и каждый производный класс также может быть добавлен к другим векторам, дублирование кода становится проблемой (BaseList.push_back(P)
следует вызывать для каждого объекта, который наследует BaseClass
и, следовательно, должны быть записаны в каждом X::MakeOne()
, где X
наследует BaseClass
).
Я также преодолел эту проблему, просто используя необработанные указатели (std::vector<BaseClass*>
), однако это теряет преимущество простого управления памятью и подсчета ссылок, когда на объекты ссылаются в нескольких местах. Есть ли лучший вариант для управления памятью в этой ситуации?