Основная причина в том, что классические C-броски не делают различий между тем, что мы называем static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
и dynamic_cast<>()
. Эти четыре вещи совершенно разные.
A static_cast<>()
обычно безопасен. Существует допустимое преобразование в языке или соответствующий конструктор, который делает это возможным. Единственный случай, когда это немного рискованно, это когда вы переходите в унаследованный класс; вы должны удостовериться, что объект действительно является потомком, который, как вы утверждаете, является внешним, по отношению к языку (например, флаг в объекте). dynamic_cast<>()
является безопасным, пока проверяется результат (указатель) или учитывается возможное исключение (ссылка).
A reinterpret_cast<>()
(или const_cast<>()
) с другой стороны всегда опасно. Вы говорите компилятору: «Поверьте мне: я знаю, что это не похоже на foo
(похоже, что оно не изменяемое), но это так».
Первая проблема заключается в том, что почти невозможно определить, какой из них произойдет при приведении в стиле C, не глядя на большие и разбросанные фрагменты кода и не зная всех правил.
Давайте предположим, что это:
class CMyClass : public CMyBase {...};
class CMyOtherStuff {...} ;
CMyBase *pSomething; // filled somewhere
Теперь эти два скомпилированы одинаково:
CMyClass *pMyObject;
pMyObject = static_cast<CMyClass*>(pSomething); // Safe; as long as we checked
pMyObject = (CMyClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read
Однако, давайте посмотрим на этот почти идентичный код:
CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!
Как видите, не существует простого способа различить две ситуации, не зная много обо всех участвующих классах.
Вторая проблема заключается в том, что броски в стиле C слишком сложны для поиска. В сложных выражениях может быть очень трудно увидеть броски в стиле C. Практически невозможно написать автоматический инструмент, который должен находить приведения в стиле C (например, инструмент поиска) без полноценного внешнего интерфейса компилятора C ++. С другой стороны, можно легко найти «static_cast <» или «reinterpret_cast <». </p>
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.
Это означает, что не только броски в стиле C более опасны, но гораздо сложнее найти их всех, чтобы убедиться, что они правильные.