Каковы примеры "хорошего использования" динамического кастинга?
Мы часто слышим/читаем, что следует избегать динамического кастинга. Мне было интересно, что будет "хорошим" примером этого, согласно вам?
Edit:
Да, я знаю этот другой поток: действительно, когда я читал один из первых ответов, я задал свой вопрос!
Ответы
Ответ 1
Этот недавний поток дает пример того, где он пригодится. Существует базовый класс Shape и классы, полученные из него Circle и Rectangle. При тестировании на равенство очевидно, что круг не может быть равен прямоугольнику, и было бы катастрофой попытаться их сравнить. Итерации через набор указателей на фигуры, dynamic_cast выполняет двойную работу, сообщая вам, сопоставляются ли фигуры и дают ли вам подходящие объекты для сравнения.
Векторный итератор не может быть разыменован
Ответ 2
Здесь что-то я часто делаю, это не красиво, но это просто и полезно.
Я часто работаю с контейнерами шаблонов, которые реализуют интерфейс,
представьте себе что-то вроде
template<class T>
class MyVector : public ContainerInterface
...
Где ContainerInterface имеет базовые полезные вещи, но все. Если мне нужен конкретный алгоритм на векторах целых чисел без представления моей реализации шаблона, полезно принять объекты интерфейса и dynamic_cast в MyVector в реализации. Пример:
// function prototype (public API, in the header file)
void ProcessVector( ContainerInterface& vecIfce );
// function implementation (private, in the .cpp file)
void ProcessVector( ContainerInterface& vecIfce)
{
MyVector<int>& vecInt = dynamic_cast<MyVector<int> >(vecIfce);
// the cast throws bad_cast in case of error but you could use a
// more complex method to choose which low-level implementation
// to use, basically rolling by hand your own polymorphism.
// Process a vector of integers
...
}
Я мог бы добавить метод Process() в ContainerInterface, который был бы полиморфно разрешен, это был бы более хороший метод ООП, но я иногда предпочитаю делать это таким образом. Когда у вас есть простые контейнеры, множество алгоритмов и вы хотите сохранить свою реализацию скрытой, dynamic_cast предлагает легкое и уродливое решение.
Вы также можете посмотреть методы двойной отправки.
НТН
Ответ 3
Мой текущий проект игрушек использует dynamic_cast дважды; один раз, чтобы обойти отсутствие множественной отправки в С++ (это система стиля посетителя, которая могла бы использовать несколько диспетчеров вместо dynamic_casts), и один раз в специальный случай - определенный подтип.
Оба из них приемлемы, на мой взгляд, хотя первые, по крайней мере, связаны с дефицитом языка. Я думаю, что это может быть обычная ситуация; большинство dynamic_casts (и большое количество "шаблонов проектирования" в целом) являются обходными решениями для конкретных языковых недостатков, а не для чего-то, что нужно.
Ответ 4
Он может использоваться для небольшого уровня безопасности во время выполнения при экспонировании дескрипторов объектов через интерфейс C. У всех открытых классов наследуется общий базовый класс. Когда вы принимаете дескриптор функции, сначала бросаете в базовый класс, а затем динамически добавляете в класс, который вы ожидаете. Если они передаются в нечувствительном дескрипторе, вы получите исключение, когда время выполнения не сможет найти rtti. Если они передаются в действительном дескрипторе неправильного типа, вы получаете указатель NULL и можете генерировать собственное исключение. Если они пройдут в правильном указателе, вам хорошо идти.
Это не безупречно, но, безусловно, лучше поймать ошибочные вызовы в библиотеки, чем прямой реинтерпрет, сделанный из дескриптора, и до тех пор, пока некоторые данные не будут таинственно повреждены, когда вы передадите неправильный дескриптор.
Ответ 5
Хорошо, было бы хорошо с методами расширения на С#.
Например, скажем, у меня есть список объектов, и я хочу получить список всех идентификаторов из них. Я могу пройти через все их и вытащить, но я хотел бы сегментировать этот код для повторного использования.
так что-то вроде
List<myObject> myObjectList = getMyObjects();
List<string> ids = myObjectList.PropertyList("id");
было бы здорово, кроме как в методе расширения, вы не будете знать тип, который входит.
So
public static List<string> PropertyList(this object objList, string propName) {
var genList = (objList.GetType())objList;
}
будет потрясающим.
Ответ 6
Это очень полезно, однако, в большинстве случаев это слишком полезно: если для выполнения работы самый простой способ - сделать dynamic_cast, это чаще всего является признаком плохого дизайна OO, что, в свою очередь, может приводят к неприятностям в будущем непредвиденными способами.