Полиморфизм в C++ с вектором с базовыми классами и reference_wrapper

Мне нужно использовать полиморфизм в C++ для объектов, которые хранятся в векторе.

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

Насколько я понимаю, std::reference_wrapper подойдет, но у меня возникли некоторые проблемы с его реализацией.

ActorRecordingItem является базовым классом, а ActorVehicleEnterRecordingItem является примером класса, который нуждается в полиморфизме (наследуется от ActorRecordingItem через ActorVehicleRecordingItem)

    class ActorRecordingItem {
protected:
    DWORD m_ticksAfterRecordStart;
    Ped m_actorPed;
    Vector3 m_location;
    DWORD m_ticksDeltaCheckCompletion;
public:
    ActorRecordingItem(DWORD ticksStart, Ped actorPed, Vector3 location);
    virtual void executeNativesForRecording(Actor actor);
    virtual bool isRecordingItemCompleted(Actor actor, Vector3 location);
    virtual std::string toString();
};

class ActorVehicleEnterRecordingItem : public ActorVehicleRecordingItem {
protected:
    int m_vehicleSeat;
    float m_enterVehicleSpeed;
public:
    ActorVehicleEnterRecordingItem(DWORD ticksStart, Ped actor, Vector3 location, Vehicle veh, int vehicleSeat,float enterVehicleSpeed);
    std::string toString() override;
    void executeNativesForRecording(Actor actor) override;
    bool isRecordingItemCompleted(Actor actor, Vector3 location) override;
};

Вектор с объектами, которым требуется полиморфизм, хранится в другом классе Actor. В настоящее время он определяется как

class Actor
{
private:
    std::vector<std::reference_wrapper<ActorRecordingItem>> m_actorRecordingItems;
public:
    Actor();
    Actor(Ped ped);
    void setRecording(std::vector<std::reference_wrapper<ActorRecordingItem>> actorRecordingItems);
    std::vector<std::reference_wrapper<ActorRecordingItem>> getRecording();
    std::reference_wrapper<ActorRecordingItem> getRecordingAt(int index);
};

С внедрением ключевых методов как

void Actor::setRecording(std::vector<std::reference_wrapper<ActorRecordingItem>> actorRecordingItems)
{
    m_actorRecordingItems = actorRecordingItems;
}

std::vector<std::reference_wrapper<ActorRecordingItem>> Actor::getRecording()
{
    return m_actorRecordingItems;
}

std::reference_wrapper<ActorRecordingItem> Actor::getRecordingAt(int index)
{
    return m_actorRecordingItems[index];
}

Элементы actorRecordingItems создаются в отдельном методе и присваиваются субъекту. Это делается через

std::vector<std::reference_wrapper<ActorRecordingItem>> actorRecording;
actorRecording.reserve(1000);

ActorVehicleEnterRecordingItem recordingItem(ticksSinceStart, actorPed, actorLocation, actorVeh, seat, enterSpeed );
actorRecording.push_back(recordingItem);

actor.setRecording(actorRecording);

Наконец, это место, где я хочу использовать их и требовать полиморфизма.

std::reference_wrapper<ActorRecordingItem> recordingItem = actor.getRecordingAt(recordingPlayback.getRecordedItemIndex());

recordingItem.get().executeNativesForRecording(actor);

Последняя строка вызывает сбой программы. Я действительно немного растерялся, когда начать изучать эту проблему, поэтому любая помощь будет высоко ценится.

PS извините за очень длинный вопрос:)

1 ответ

Решение

Проблема в этих строках:

ActorVehicleEnterRecordingItem recordingItem(ticksSinceStart, actorPed, actorLocation, actorVeh, seat, enterSpeed );
actorRecording.push_back(recordingItem);

Здесь происходит то, что вы создаете локальную переменную и помещаете ссылку на локальную переменную в вектор. Ссылка становится недействительной, как только переменная recordingItem выходит за рамки. std::reference_wrapper это именно то, что говорится в названии - это обертка для ссылки, и она не осуществляет какого-либо управления ресурсами. Вы можете обойти эту проблему, имея вектор std::unique_ptr, std::shared_ptr или если вы хотите избежать динамического выделения для каждого элемента - boost::variant<> (в этом случае вам нужно будет указать все потенциальные типы, которые могут быть в векторе).

Другие вопросы по тегам