I need to use polymorphism in C++ for objects which are stored in a vector.
Understand from other questions that the objects in the vector need to be stored by reference since otherwise object slicing occurs.
My understanding is that std::reference_wrapper would be a good fit, but I'm having some issues implementing it.
ActorRecordingItem is the base class and ActorVehicleEnterRecordingItem is an example of a class which needs polymorphism (inherts from ActorRecordingItem via 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;
};
The vector with the objects which needs polymorphism is stored in another class Actor. It's currently defined as
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);
};
With implementation of the key methods as
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];
}
The actorRecordingItems are created in a separate method and assigned to the actor. This is done through
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);
Lastly is the location where I want to use them and require the polymorphism.
std::reference_wrapper<ActorRecordingItem> recordingItem = actor.getRecordingAt(recordingPlayback.getRecordedItemIndex());
recordingItem.get().executeNativesForRecording(actor);
The last line appears to cause the program to crash. I'm really a bit lost on where to start looking into this problem, so any assistance would be much appreciated
PS sorry for the very long question :)
The problem is in these lines:
ActorVehicleEnterRecordingItem recordingItem(ticksSinceStart, actorPed, actorLocation, actorVeh, seat, enterSpeed );
actorRecording.push_back(recordingItem);
What is happening here is that you create a local variable and push a reference to the local variable to the vector. The reference becomes invalid as soon as the variable recordingItem
goes out of scope. std::reference_wrapper
is exactly what the name states - it is a wrapper for a reference and it doesn't do any kind of management of resources. You can circumvent this problem by having a vector of std::unique_ptr
, std::shared_ptr
or if you want to avoid dynamic allocation for each element - boost::variant<>
(in this case you will need to specify all the potential types that could be in the vector).