Как я могу безопасно приводить (т.е. возвращать null в случае сбоя) к точному типу базового объекта, не подвергаясь штрафу за производительность dynamic_cast
и не добавляя код поддержки в каждый используемый класс?
Отказ от dynamic_cast для приведения к исходному типу
Ответы (1)
dynamic_cast
будет проходить по всему дереву наследования, чтобы увидеть, возможно ли желаемое преобразование. Если все, что вам нужно, это прямое приведение к типу того же, что и объект, и вам не нужна возможность перекрестного приведения, приведения через виртуальное наследование или приведения к базовому классу объекта фактический тип объекта, будет работать следующий код:
template<class To>
struct exact_cast
{
To result;
template<class From>
exact_cast(From* from)
{
if (typeid(typename std::remove_pointer<To>::type) == typeid(*from))
result = static_cast<To>(from);
else
result = 0;
}
operator To() const
{
return result;
}
};
Семантика точно такая же, как и для других операторов приведения, т.е.
Base* b = new Derived();
Derived* d = exact_cast<Derived*>(b);
Изменить: я протестировал это в проекте, над которым работаю. Мои результаты от QueryPerformanceCounter
:dynamic_cast
: 83 024 197exact_cast
: 78 366 879
Это ускорение на 5,6%. Это для нетривиального кода, привязанного к процессору. (Он не выполняет ввод-вывод)
person
Dan
schedule
15.07.2012
Есть ли доказательства того, что это более эффективно, чем
dynamic_cast
?
- person Oliver Charlesworth; 15.07.2012
Кроме того, почему класс вместо функции?
- person avakar; 15.07.2012
@OliCharlesworth: я не удивлюсь, если это будет более эффективно (получение
typeinfo
должно быть всего в нескольких разыменованиях, без больших вычислений).
- person Matthieu M.; 15.07.2012
Этот код оказался на 0,05 секунды быстрее по сравнению с
dynamic_cast
в моем тесте на 4 000 000 итераций построения полиморфного объекта в куче и присвоения базовому указателю, приведения к производному и его освобождения (с уровнем оптимизации -Ofast
в gcc 4.7. 1).
- person Seth Carnegie; 15.07.2012
@Сет Карнеги: я неправильно понял код. Я удалил комментарий.
- person AnT; 15.07.2012
@Nicol Bolas: Это, вероятно, то, что OP имел в виду, говоря, что все, что вам нужно, это прямое приведение к типу того же, что и объект. Это же должно означать, что вам разрешено приводить только к наиболее производному типу объекта, а не к промежуточным базам. Это, конечно, сильно ограничивает возможности использования данного приведения.
- person AnT; 15.07.2012
@AndreyT Вот что я имел в виду. Я уточню это.
- person Dan; 15.07.2012
@NicolBolas Это правда. Я обновил вопрос до того, что я хотел сказать.
- person Dan; 15.07.2012
dynamic_cast
не реализовать этот метод? - person Konrad Rudolph   schedule 15.07.2012dynamic_cast
строго мощнее. По сути, это особый случай использования. - person Dan   schedule 15.07.2012