2008-08-26 2 views
22

Мы часто слышим/читаем, что следует избегать динамического каста. По-моему, мне было интересно, что будет «хорошим» примером?Каковы примеры «хорошего использования» динамического каста?

Edit:

Да, я в курсе that other thread: это действительно, читая один из первых ответов там, что я спросил мой вопрос!

+12

Название этого вопроса не соответствует описанию. – bradtgmurray 2009-07-07 20:06:01

ответ

0

Мой текущий проект игрушек использует dynamic_cast дважды; один раз, чтобы обойти отсутствие множественной отправки в C++ (это система стиля посетителя, которая может использовать несколько диспетчеров вместо dynamic_casts) и один раз для специального случая - определенный подтип.

Оба эти варианта приемлемы, на мой взгляд, хотя первые, по крайней мере, связаны с дефицитом языка. Я думаю, что это может быть обычная ситуация; большинство dynamic_casts (и большое количество «шаблонов проектирования» в целом) являются обходными решениями для конкретных языковых недостатков, а не для чего-то, к чему стремятся.

0

Его можно использовать для обеспечения безопасности во время выполнения при экспонировании дескрипторов объектов через интерфейс C. У всех открытых классов наследуется общий базовый класс. Когда вы принимаете дескриптор функции, сначала бросаете в базовый класс, а затем динамически добавляете в класс, который вы ожидаете. Если они передаются в нечувствительном дескрипторе, вы получите исключение, когда время выполнения не сможет найти rtti. Если они передаются в действительном дескрипторе неправильного типа, вы получаете указатель NULL и можете генерировать собственное исключение. Если они пройдут в правильном указателе, вам хорошо идти. Это не безупречно, но это, безусловно, лучше поймать ошибочные вызовы в библиотеки, чем прямой реинтерпрет, снятый с ручки, и до тех пор, пока некоторые данные не будут таинственно повреждены, когда вы передадите неправильную ручку.

1

Я часто это делаю, это некрасиво, но это просто и полезно.

Я часто работаю с контейнерами шаблонов, которые реализуют интерфейс, представить себе что-то вроде

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 предлагает легкое и уродливое решение.

Вы также можете ознакомиться с методами двойной отправки.

НТН

0

Ну это было бы действительно хорошо с методами расширения в C#.

Например, допустим, у меня есть список объектов, и я хочу получить список всех идентификаторов из них. Я могу пройти через все их и вытащить, но я хотел бы сегментировать этот код для повторного использования.

так что-то вроде

List<myObject> myObjectList = getMyObjects(); 

List<string> ids = myObjectList.PropertyList("id"); 

было бы круто, кроме как на метод расширения вы не будете знать тип, который приходит в.

Так

public static List<string> PropertyList(this object objList, string propName) { 
    var genList = (objList.GetType())objList; 
} 

было бы удивительным.

9

Эта недавняя нить дает пример того, где она пригодится. Существует базовый класс Shape и классы, полученные из него Circle и Rectangle. При тестировании на равенство очевидно, что круг не может быть равен прямоугольнику, и было бы катастрофой попытаться их сравнить. Итерация через набор указателей на фигуры, dynamic_cast делает двойной долг, сообщая вам, сопоставляются ли фигуры и дают вам соответствующие объекты для сравнения.

Vector iterator not dereferencable

0

Это очень полезно, однако, в большинстве случаев это является слишком полезно: если для получения задания сделать самый простой способ это сделать dynamic_cast, это чаще всего не симптом плохой дизайн OO, что, в свою очередь, может привести к неприятностям в будущем непредвиденными способами.

Смежные вопросы