Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 55
Текст из файла (страница 55)
Динамическая идентификаций и приведение типов375// Фабрика производных от класса Num объектовNum<double> *generator()switch(rand() % 2) {case 0: return new Squary<double> (randf) % 100);case 1: return new Sqr_root<double> (rand() % 100};return NULL;intmain()Num<double> obl(lO), *pl;Squary<double> ob2 (100.0), *p2;Sqr_root<double> ob3(999.2), *p3;int i;cout « "Генерируем несколько объектов\п";for(i=0; i<10; i++) {pi = generator ( } ;p2 = dynamic_cast<Squary<double> *> (pi);if(p2) cout « "Квадрат объекта: ";рЗ = dynamic_cast<Sqr_root<double> *> (pi);if(p3) cout « "Квадратный корень объекта:cout « "Значение равно: " « pl->get_val {)cout « endl;}return 0;1.
Своими словами объясните назначение оператора dynamic_cast.2. Дан следующий фрагмент программы. Покажите, как с помощью оператораdynamic_cast сделать так, чтобы указатель р указывал на некоторый объект obтолько в том случае, если объект ob является объектом типа D2.class В {virtual void f ( ) {}};class Dl: public В {void f ( } { }};Самоучитель C++376class D2 : public В {void f { ) {}3. Переделайте функцию main() из раздела 12.1, упражнение 4 так, чтобы длязапрещения вывода на экран объектов типа NuMShape использовался не оператор typeid, а оператор dynamic_cast.4. Будет ли работоспособен следующий фрагмент программы в иерархии классов с базовым классом Num из примера 3 этого раздела?Num<int> *Вр;Square<double> *Dp;Dp = dynamic cast<Num<int» (Bp) ;12.3. Операторы const_cast,reinterpret_cast и staticjcastХотя оператор dynamic_cast самый полезный из новых операторов приведения типов, кроме него программистам доступны еще три.
Ниже представлены их основные формы:сопз1:_сазЬ<целевой_тяп> (выражение)__(выражение)static_cast<4&neBa#__!TJim> (выражение)Здесь целевой_тип — это тип, которым должен стать тип параметра выражение после выполнения операции приведения типов. Как правило, указанныеоператоры обеспечивают более безопасный и интуитивно понятный способвыполнения некоторых видов операций преобразования, чем оператор приведения типов, более характерный для языка С.Оператор const_cast при выполнении операции приведения типов используется для явной подмены атрибутов const (постоянный) и/или volatile(переменный).
Целевой тип должен совпадать с исходным типом, за исключением изменения его атрибутов const или volatile. Обычно с помощью оператора const_cast значение лишают атрибута const.Оператор static_cast предназначен для выполнения операций приведениятипов над объектами неполиморфных классов. Например, его можно использовать для приведения типа указателя базового класса к типу указателяпроизводного класса. Кроме этого, он подойдет и для выполнения любойГлава 12. Динамическая идентификация и приведение типов377стандартной операции преобразования, но только не в динамическом режиме (т.
е. не во время выполнения программы).Оператор reinterpret_cast дает возможность преобразовать указатель одноготипа в указатель совершенно другого типа. Он также позволяет приводитьуказатель к типу целого и целое к типу указателя. Оператор reinterpret_castследует использовать для выполнения операции приведения внутренне несовместимых типов указателей.Атрибута const объект можно лишить только с помощью оператораconst_cast. С помощью оператора dynamic_cast, static_cast или reinterpret_castэтого сделать нельзя.ры ]Примеры>^1. В следующейreinterpret_cast.программедемонстрируетсяиспользованиеоператора// Пример использования оператора reinterpret_castttinclude <iostream>using namespace std;int{main{)int i ;char *p = "Это строка";// приведение типа указателя к типу целогоi = reinterpret_cast<int> (p} ;cout « i;return 0;В данной программе с помощью оператора reinterpret_cast указатель на строку превращен в целое.
Это фундаментальное преобразование типа и оно хорошо отражает возможности оператора reinterpret_cast.2. В следующей программе демонстрируется оператор const_cast// Пример использования оператора const_cast#include <iostream>using namespace std;void f (const int *p){int *v;378Самоучитель C++11 преобразование типа лишает указатель р атрибута constv = const_cast<int *> (р);*v = 100; // теперь указатель v может изменить объектIint main(){int x = 99;cout « "Объект х перед вызовом функции равен: " « х « endl;f(&x);cout « "Объект х после вызова функции равен: " « х « endl;return 0;Ниже представлен результат выполнения программы:Объект х перед вызовом функции равен: 99Объект х после вызова функции равен: 100Как видите, несмотря на то что параметром функции f() задан постоянныйуказатель, вызов этой функции с объектом х в качестве параметра изменилзначение объекта.Возможность снятия оператором constjcast атрибута const при выполненииоперация приведения типов потенциально очень опасна.
Пользоваться этойвозможностью следует с величайшей осторожностью.3. Оператор static_cast, по существу, предназначен для замены прежнего оператора приведения типов. Он просто выполняет операцию приведения типовнад объектами неполиморфных классов. Например, в следующей программетип float приводится к типу int.// Пример использования оператора static__cast^include <iostream>using namespace std;int main(}{int i;float f;f = 199.22;i = static cast<int> ( f } jГлава 12.
Динамическая идентификация и приведение типов379cout « i;return 0;Упражнения1. Объясните, зачем нужны операторы const_cast, reinterpret_cast и static^cast.2. В следующей программе имеется ошибка. Исправьте ее с помощью оператора const_cast.#include <iostream>using namespace std;void f (const double & i ){i = 100; // Ошибка! Исправьте ее с помощью оператора const_castIint{main()double x = 98.6;cout « x « endl;f (x);cout « x « endl;return 0;13. Объясните, почему оператор const_cast следует использовать только в самыхкрайних случаях.Проверка усвоенияматериала главыТеперь вам необходимо выполнить следующие упражнения и ответить навопросы.1.
Опишите операции, которые можно выполнить с помощью оператораtypeid.2. Какой заголовок нужно включить в вашу программу для использованияоператора typeid?Самоучитель C++3803. Помимо стандартного приведения типов, в C++ определено для этой цели еще четыре оператора. Что это за операторы и зачем они нужны?4. Допишите следующую программу, чтобы на экран выводилась информация о выбранном пользователем типе объекта.^include <iostream>#include <typeinfo>using namespace std;class A {virtual void f(}•{}class B: public A {class C: public В {int main{)A *p, a_ob;В b_ob;С c_ob;int i;cout « "Введите О для объектов типа А,";cout « "1 для объектов типа В или";cout « "2 для объектов типа С.\п";cin » i;if (i-=l> p = &b_ob;else if (i==2) p = Sc_ob;else p = &a__ob;// выведите на экран сообщение о типе// выбранного пользователем объектаreturn 0;5.
Объясните, каким образом оператор typeid можно иногда заменить оператором dynamic_cast6. Тип какого объекта можно определить с помощью оператора typeid?Глава 12. Динамическая идентификация и приведение типов35?Проверка усвоенияматериала в целомВ этом разделе проверяется, хорошо ли вы усвоили материал этой и предыдущих глав.1. Переделайте программу из раздела 12.1, пример 4, чтобы возможнуюошибку выделения памяти внутри функции generator() отслеживать с помощью механизма обработки исключительных ситуаций.2.
Измените функцию generator() из вопроса 1, чтобы в ней использоватьверсию оператора new с ключевым словом nothrow.3. Особо сложное задание: попытайтесь создать иерархию классов с абстрактным классом DataStruct на ее вершине. В основании иерархии создайте два производных класса.
В одном должен быть реализован стек, вдругом — очередь. Создайте также функцию DataStructFactoryQ со следующим прототипом:DataStruct *DataStructFactory(char метка);Функция DataStructFactoryO должна создавать стек, если параметр метка равен s, и очередь, если параметр метка равен q. Возвращаемым значением функции должен быть указатель на созданный объект. Покажите,что ваша "фабрика объектов" работает.Глава 13Пространства имени другие темыВ этой главе рассказывается о пространствах имен (namespaces), функцияхпреобразования (conversion functions), статических (static) и постоянных(const) членах класса, а также о других необычных инструментах C++.Повторение пройденногоПеред тем как продолжить, необходимо правильно ответить на следующиевопросы и сделать упражнения.1.