преобразование std :: shared_ptr с использованием std :: dynamic_pointer_cast

Я начинаю работать с умными указателями в C ++ 0X / 11, и я столкнулся с особой ситуацией.
Я хочу выполнить приведение экземпляра объекта с использованием shared_ptr.

Класс Extend наследуется от класса Base, где в базовом классе есть виртуальный деструктор, чтобы сделать его полиморфным (в противном случае dynamic_pointer_cast жалуется на неполиморфное приведение классов).

если поэтому:

std::shared_ptr<Base> obj = std::make_shared<Base>();

и тогда я делаю:

obj = std::dynamic_pointer_cast<Extend>(obj);
  1. Это безопасно ?
  2. Что происходит с другими указателями на объект? Только obj рассматривает его как Extend, в то время как другие общие указатели все равно будут рассматривать его как Base?
  3. Безопасно ли использовать тот же экземпляр или я должен сделать что-то еще?

РЕДАКТИРОВАТЬ: Спасибо за ответы. Реальная причина, по которой я задавал этот вопрос, заключалась в обработке документов XML с использованием синтаксического анализатора SAX, но я увлекся приведением вверх / вниз.
То, что я вроде хотел, было:

std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;

Но в этом нет никакого смысла, вместо этого я просто использую фабрику объектов.

9

Решение

Это не повышающий, а понижающий (вы переходите из более низкого класса в более производный). Тем не мение:

Это безопасно?

Да, это безопасно, но так как вы пытаетесь уменьшить указатель на объект, тип времени выполнения которого не Extend, вы получите нулевой указатель в ответ.

Что происходит с другими указателями на объект? Только obj рассматривает его как Extend, в то время как другие общие указатели все равно будут рассматривать его как Base?

Здесь у вас неправильное представление: снижение указателя на объект не трансформирует объект. Если объект не относится к целевому типу, вы не получите пониженный указатель на него. Тип заостренного объекта (из любой объект) определяется во время компиляции и не изменится.

Безопасно ли использовать тот же экземпляр или я должен сделать что-то еще?

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

obj = std::dynamic_pointer_cast<Extend>(obj);

Сделаю obj нулевой указатель. Само назначение является законным, так как вы Можно назначить (умный) указатель на производный класс (умному) указатель на базовый класс. Однако, поскольку правая часть присваивания оценивается как нулевой указатель (из-за того, что написано выше), вы в конечном итоге получите нулевой указатель, назначенный для obj,

Так как вы в основном просто сбрасываете obj, если obj последний общий указатель на объект, созданный через make_shared<>(), этот объект будет уничтожен после выполнения вышеуказанного присваивания.

10

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

Вы можете приводить только к типу super, если базовый объект действительно принадлежит к этому типу. Приведение не может внезапно дать вашему базовому объекту новые свойства.

std::make_shared<Base>();

Будем под прикрытием звонить: new Base,

Это означает, что вы не можете:

obj = std::dynamic_pointer_cast<Extend>(obj);

Больше, чем вы могли бы использовать dynamic_cast на new Base чтобы превратить это во что-то, что это не так. Вам нужно будет make_shared<Extend> а затем передать его с помощью shared_ptr<Base>,

6

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