Стандарты программирования на С++




Обсуждение


Одна из проблем, связанных с преобразованием типов в стиле С, заключается в том, что оно использует один и тот же синтаксис для выполнения несколько разных вещей, в зависимости от таких мелочей, как, например, какие именно заголовочные файлы включены при помощи директивы #include. Преобразования типов в стиле C++, сохраняя определенную опасность, присущую преобразованиям вообще, имеют четко документированное предназначение, их легко найти, дольше писать (что дает время дважды подумать при их использовании), и не позволяют незаметно выполнить опасное преобразование reinterpret_cast (см. рекомендацию 92).

Рассмотрим следующий код, в котором Derived — производный от базового класса Base:

extern void Fun( Derived* );

void Gun( Base* pb ) { // Будем считать, что функция Gun знает, что pb в // действительности указывает на объект типа Derived и // хочет передать его функции Fun Derived* pd = (Derived*)pb; // Плохо: преобразование Fun( pd ); // в стиле C }

Если функция Gun имеет доступ к определению Derived (например, при включении заголовочного файла derived.h), то компилятор имеет всю необходимую информацию о размещении объекта, чтобы выполнить все необходимые действия по корректировке указателя при преобразовании от Base к Derived. Но если автор Gun забыл включить соответствующий файл определения, и функции Gun видно только предварительное объявление класса Derived, то компилятор будет полагать, что Base и Derived— несвязанные типы, и интерпретирует биты указателя Base* как биты указателя Derived*, не делая никаких коррекций, которые могут диктоваться размещением объекта в памяти!

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

extern void Fun( Derived* );

void Gun( Base* pb ) { // Если мы гарантированно знаем, что pb на самом деле // указывает на объект типа Derived:

// Преобразование в стиле C++ Derived* pd = static_cast<Derived*>(pb);




Содержание  Назад  Вперед