Я следую за дизайном архитектуры игрового объекта presented by Marcin Chady. В качестве краткого описания класс Game Object может содержать несколько экземпляров подкласса атрибутов и поведения. Объекты игры также содержатся в классе Scene. Эта схема может прояснить вещи:C++ композиция с использованием умных указателей
Поведение подклассы должны быть в состоянии получить доступ к их родительским Game класса Object. Это необходимо, так как поведение должно иметь возможность читать и записывать различные атрибуты и подписываться на получение событий от игрового объекта. Некоторым поведением также может потребоваться доступ к сцене родительского игрового объекта, чтобы они могли создавать экземпляры других игровых объектов.
В настоящее время я использую общие указатели и слабые указатели. Например, класс Game Object содержит vector<shared_ptr<Attribute>>
и vector<shared_ptr<Behaviour>>
. Затем классы поведения и атрибута содержат weak_ptr<GameObject>
. Это нарушает опорный цикл.
Теперь, если поведение хочет получить доступ к сцене, он должен выполнить несколько вложенных слабые указатели замков:
if (std::shared_ptr<GameObject> sharedGameObject = GetGameObject().lock())
{
if (std::shared_ptr<Scene> sharedScene = sharedGameObject->GetScene().lock())
{
// Do something with the scene.
}
}
Это может получить немного грязное. Если нам нужно получить доступ к классу Application, тогда потребуются 3 вложенных блокировки. Это явно не требуется при использовании исходных указателей. Использую ли я правильные умные указатели? Если я есть, есть ли что-нибудь, что я могу сделать, чтобы привести в порядок это, или это то, с чем мне просто придется жить?
Одно из возможных решений: полностью удалить объекты weak_ptr. В идеале для объектов Behavior и Attribute вообще не нужно обращаться к GameObject, но если они абсолютно необходимы, передайте им указатель GameObject (или ссылку) в качестве аргумента методам, который вы им вызываете. –
Почему вы используете интеллектуальные указатели здесь. Кажется, что нет необходимости. –
Вы можете закодировать его с помощью общих петель указателей, а затем вызвать метод выключения, когда вы хотите, чтобы объект уходил. В методе выключения вы можете сбросить общие указатели, чтобы удалить целевые объекты. Вероятно, вам все равно придется протестировать указатели, прежде чем использовать их, чтобы убедиться, что они не были сброшены, но это позволяет избежать хита производительности слабой блокировки указателя. –