деструктор — C ++ разделяет указатели классов parent-child

У меня есть сценарий, в котором мне нужно собрать все объекты типа в коллекции, но мне также нужна коллекция некоторых из его унаследованных типов. Пример:

class Particle: public someClass
{
...
public:
static std::vector<std::shared_ptr<Particle>> particleCollection;
}

class ChargedParticle: public Particle
{
...
public:
static std::vector<std::shared_ptr<ChargedParticle>> chargedParticleCollection;
}

Однако когда я хочу уничтожить эти объекты, я на самом деле вызываю деструктор дважды для каждой ChargedPartice:

Particle::particleCollection.clear(); // Okay
ChargedParticle::chargedParticleCollection.clear(); // Error: particles are already deleted

Как я могу иметь коллекцию дочерних объектов, хранящихся в его статическом контейнере, и иметь умные указатели, указывающие на них одним из их родительских классов?

Я хочу иметь возможность создавать объекты и из родительского класса, и иметь статический вектор интеллектуального указателя родителя, который будет владельцем этих объектов.

Моя идея состоит в том, что я каким-то образом определяю пользовательское средство удаления для интеллектуальных указателей родительского класса, которое вызывает только деструктор, когда объект не является элементом коллекции дочернего класса. Это возможно?

-3

Решение

каждый ChargedParticle в то же время является Particle так зовет Particle::particleCollection.clear(); будет достаточно, чтобы удалить все выделенные объекты.

Чтобы использовать разделяемый указатель в вашем случае, вы должны иметь базовый класс (либо someClass или же Particle) быть унаследованным от std:: enable_shared_from_this таким образом, общий указатель, созданный из него, будет использовать тот же счетчик. В вашем примере это два разных экземпляра общего указателя, которые ничего не знают друг о друге.

И я не вижу причин для того, чтобы виртуального деструктора не хватало для ваших нужд.

1

Другие решения

Если вы используете его правильно, проблем нет, имя класса не совпадает с именем вашего класса, но я не думаю, что это имеет значение:

#include <iostream>
#include <type_traits>
#include <tuple>
#include <vector>
#include <memory>
struct Base
{
Base() { std::cout << "  Base::Base()\n"; }
// Note: non-virtual destructor is OK here
~Base() { std::cout << "  Base::~Base()\n"; }
};

struct Derived: public Base
{
Derived() { std::cout << "  Derived::Derived()\n"; }
~Derived() { std::cout << "  Derived::~Derived()\n"; }
};

int main() {
std::vector<std::shared_ptr<Base>> base_vector;
std::vector<std::shared_ptr<Derived>> derived_vector;
auto d = std::make_shared<Derived>();
derived_vector.push_back(d);
base_vector.push_back(d);
// 2 function call below does not matter
base_vector.clear();
derived_vector.clear();

}

демонстрация расширен от примера в Cpp Ссылка

Вы не можете создать саморегистрационный класс с std::shared_ptr потому что вам нужно наследовать от std::enable_shared_from_this, но ты не можешь позвонить shared_from_this() в конструкторе потому что:

Разрешается вызывать shared_from_this только для ранее общего объекта, то есть для объекта, управляемого std :: shared_ptr. В противном случае поведение не определено (до C ++ 17), генерируется std :: bad_weak_ptr (с помощью конструктора shared_ptr, созданного по умолчанию weak_this) (начиная с C ++ 17).

0

По вопросам рекламы [email protected]