2017-01-12 4 views
0
#include <iostream> 

class Base { 
}; 

class Derived : public Base { 
}; 

int main() { 
    Base* bptr = new Derived(); 

    Derived* dptr = static_cast<Derived*>(bptr); 

    std::cout << dptr << std::endl; 
} 

В приведенном выше коде я должен использовать dynamic_cast, но я неправильно использую static_cast. static_cast никогда не должен использоваться в то время как downcasting, поскольку у компилятора нет способа определить, что мы делаем правильно.C++ static_cast vs dynamic_cast

Почему это не ошибка компиляции? Я использую gcc 4.9.2. Вы, ребята, думаете, что это ошибка в компиляторе, или же стандарты C++ допускают такой код?

Редактировать: Спасибо за ответы. На самом деле, базовый класс выше - полиморфный , т. Е. Он имеет виртуальные функции, но я оставил их для этого примера. Я должен бросить в виртуальный деструктор в базе, чтобы было ясно, что он был полиморфным - мой плохой.

+5

Вы можете использовать 'static_cast' от' Base * 'до 'Derived *', но вы правы, что он не будет выполнять проверку типов. Это все же полезно, хотя, если вы знаете каким-то другим способом, что этот указатель действительно указывает на объект 'Dervied'. Если 'Base *' на самом деле не указывает на 'Derived * ', то любое разыменование' Derived' ', вызванное' static_cast', вызовет неопределенное поведение. –

+0

Во всей реальности это * точно * то, что для 'static_cast'is; в конце концов, преобразования в указатели базового класса/ссылки выполняются неявно. –

ответ

1

static_cast <new_type> (expression)

Если new_type является указателем или ссылка некоторого класса D и типа expression представляет собой указатель или ссылку на его невиртуальную базе В, static_cast выполняет подавленный. Этот downcast плохо сформирован, если B является двусмысленной, недоступной или виртуальной базой (или базой виртуальной базы) D. Такой static_cast не выполняет проверки во время выполнения, чтобы гарантировать, что тип выполнения объекта фактически является D, и может использовать только безопасно, если это условие гарантировано другими способами, например, когда реализует статический полиморфизм. Безопасное подавление может быть выполнено с помощью dynamic_cast.

Source (пункт 2 Пояснение)

4

В приведенном выше коде, я должен использовать dynamic_cast, но я использую static_cast неправильно. static_cast никогда не должен использоваться во время downcasting, поскольку компилятор не может определить, что мы делаем корректно.

По иронии судьбы, dynamic_cast на самом деле был бы плохо сформированным, потому что ваши типы не являются полиморфными.

Это, пожалуйста, static_cast можно, конечно, использовать для понижения. Вы правы, что компилятор не может выполнять проверку типов, но есть много ситуаций, в которых у вас есть Base*, и знаете, что он указывает на Derived*, поэтому вы можете просто вручную выполнить трансляцию. Один очень распространенный случай CRTP:

template <class Derived> 
class Base { 
    Derived& self() { return *static_cast<Derived*>(this); } 
    // ... 
}; 


class Foo : Base<Foo> { ... }; 

Base<T> является всегдаT, так что опущенными безопасно.

Преимущество static_cast над dynamic_cast что static_cast является бесплатным, но dynamic_cast дорого. Манга C++ не оплачивает то, что вам не нужно.

0

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

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

Классы без виртуальных функций, как и ваши классы примеров, не несут эту информацию о времени выполнения, а dynamic_cast не могут использоваться для перевода в более производный тип. (Его все равно можно использовать для приведения к одному типу или базовому классу, то есть его можно использовать для преобразований, которые фактически не нуждаются в литье.)

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