reinterpret_cast<type> (expr)
Здесь элемент type задает новый тип операции приведения, а элемент expr означает выражение, которое приводится к этому новому типу.
Использование оператора reinterpret_cast демонстрируется в следующей программе.
// Пример использования оператора reinterpret_cast.
#include <iostream>
using namespace std;
int main()
{
int i;
char *p = "Это короткая строка.";
i = reinterpret_cast<int> (p); // Приводим указатель к типу int.
cout << i;
return 0;
}
Здесь оператор reinterpret_cast преобразует указатель p в целочисленное значение. Данное преобразование представляет фундаментальное изменение типа.
Кому-то из читателей могло бы показаться, что описанные выше четыре cast-оператора полностью заменяют традиционную операцию приведения типов. И тогда у них может возникнуть такой вопрос: "Стоит ли всегда вместо обычной операции приведения типов использовать более новые средства?". Дело в том, что общего правила для всех программистов не существует. Поскольку новые операторы были созданы для повышения безопасности довольно рискованной операции приведения одного типа данных к другому, многие С++-программисты убеждены, что их следует использовать исключительно с этой целью. И здесь трудно что-либо возразить. Другие же программисты считают, что поскольку традиционная операция приведения типов служила им "верой и правдой" в течение многих лет, то от нее не стоит так легко отказываться. Например, для выполнения простых и относительно безопасных операций приведения типов (как те, что требуются при вызове функций ввода-вывода read() и write(), описанных в предыдущей главе) "старое доброе" средство вполне приемлемо.
Существует еще одна точка зрения, с которой трудно не согласиться: при выполнении операций приведения полиморфных типов определенно стоит использовать оператор dynamic_cast.
Глава 20: Пространства имен и другие темы
В этой главе описаны пространства имен и такие эффективные средства, как explicit-конструкторы, указатели на функции, static-члены, const-функции-члены, альтернативный синтаксис инициализации членов класса, операторы указания на члены, ключевое слово asm, спецификация компоновки и функции преобразования.
Пространство имен определяет некоторую декларативную область.
Пространства имен мы кратко рассмотрели в главе 2. Они позволяют локализовать имена идентификаторов, чтобы избежать конфликтных ситуаций с ними. В С++-среде программирования используется огромное количество имен переменных, функций и имен классов. До введения пространств имен все эти имена конкурировали за память в глобальном пространстве имен, что и было причиной возникновения многих конфликтов. Например, если бы в вашей программе была определена функция toupper(), она могла бы (в зависимости от списка параметров) переопределить стандартную библиотечную функцию toupper(), поскольку оба имени должны были бы храниться в глобальном пространстве имен. Конфликты с именами возникали также при использовании одной программой нескольких библиотек сторонних производителей. В этом случае имя, определенное в одной библиотеке, конфликтовало с таким же именем из другой библиотеки. Подобная ситуация особенно неприятна при использовании одноименных классов. Например, если в вашей программе определен класс VideoMode, и в библиотеке, используемой вашей программой, определен класс с таким же именем, конфликта не избежать.
Для решения описанной проблемы было создано ключевое слово namespace. Поскольку оно локализует видимость объявленных в нем имен, это значит, что пространство имен позволяет использовать одно и то же имя в различных контекстах, не вызывая при этом конфликта имен. Возможно, больше всего от нововведения "повезло" С++-библиотеке стандартных функций. До появления ключевого слова namespace вся С++-библиотека была определена в глобальном пространстве имен (которое было, конечно же, единственным). С наступлением namespace-"эры" С++-библиотека определяется в собственном пространстве имен, именуемом std, которое значительно понизило вероятность возникновения конфликтов имен. В своей программе программист волен создавать собственные пространства имен, чтобы локализовать видимость тех имен, которые, по его мнению, могут стать причиной конфликта. Это особенно важно, если вы занимаетесь созданием библиотек классов или функций.