Серьезная проблема проектирования?
Указатель this
не может быть заблокирован.Как и во всех необработанных указателях, вы должны быть уверены, что он действителен перед разыменованием.
Но это еще не все: что, если Foo
, который вызывал fun2()
, был локальным объектом с длительностью автоматического хранения?
- Если вы уничтожите объект в вызове функции, вызвав его деструктор, вы должны будете убедиться, что в том же месте все еще есть действительный объект: в противном случае автоматический вызов деструктора привыход из блока, в котором был определен объект, может привести к неопределенному поведению.
- Если бы вы
delete
вместо того, чтобы просто уничтожить объект, это было бы неопределенным поведением в любом случае .
Альтернативный дизайн с помощью умных указателей
Одним из выходов из этой ситуации может быть создание всех объектов Foo
и Bar
с использованием фабрик (созданиеубедитесь, что конструктор не является общедоступным), и пусть эти фабрики возвращают shared_ptr
.
Это имеет то преимущество, что если объект больше не используется, он уничтожит себя.Это намного чище, чем управлять уничтожением вручную.
Однако вы столкнетесь с несколькими проблемами:
- Вам придется реорганизовать весь код, чтобы заменить необработанные указатели умными указателями
- , чтобы избежать бесконечныхв прямом эфире из-за перекрестных ссылок (два объекта держат указатель slart на другой), вам необходимо выяснить, когда использовать
shared_ptr
(если указатель должен гарантировать, что объект еще жив) и когда использовать weak_ptr
(т.е. указатель, который не способствует поддержанию объектов в живых).
Альтернативный дизайн с состояниями
Другой альтернативой будет использование состояний для определения различий между активным объектом, который можно использовать, и умершим объектом, который больше не должен использоваться.Поэтому вместо удаления объекта вы вызываете функцию изменения состояния, которая очищает / сбрасывает объект.
Это может быть реализовано:
- или очень хорошо с шаблоном проектирования состояний (но это может потребовать некоторого обширного рефакторинга),
- или с простым флагом.Затем он будет проверяться в начале каждой функции-члена и перед доступом к элементам данных, которые следует за вызовом, который потенциально может изменить состояние объекта.Это все еще подвержено ошибкам и требует анализа, но потребует в основном «локальных» изменений и, таким образом, дает большую гибкость для рефакторинга.
Преимущество этого подхода состоит в том, что функция изменения состояния будет очень простой (большинство вещей, которые у вас есть в настоящее время в деструкторе, но избежать их, может быть сделано случайно во второй раз) и сделатьхитрая часть очень хорошо видна.
Сложность будет заключаться в том, чтобы убитые предметы были очищены навсегда.Поэтому вам необходимо решить проблему владения, которая уже упоминалась ранее, и убедиться, что объекты не удаляются в середине их действий.