Каковы примеры "хорошего использования" динамического кастинга?

Мы часто слышим/читаем, что следует избегать динамического кастинга. Мне было интересно, что будет "хорошим" примером этого, согласно вам?

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, что, в свою очередь, может приводят к неприятностям в будущем непредвиденными способами.