|
Программирование >> Инициализация объектов класса, структура
class employee { public: virtual int salary(); class manager : public employee { public: int salary(); class programmer : public employee { public: int s int int salary(); int bonus(); Напомним, что payroll() принимает в качестве параметра указатель на базовый класс employee. Мы можем применить оператор dynamic cast для получения указателя на void company::payroll( employee *pe ) { programmer *pm = dynamic cast< programmer* >( pe ); апёё pe oeagflaaao ia lauaeo oeia programmer, 61 dynamic cast aflileieony 6nia0il ё pm aoaao 6ea5flaa6u ia ia+ael lauaeOa programmer if ( pm ) { enlleuglaaOu pm aey aflglaa programmer::bonus() апёё pe ia 6ea5flaaa6 ia lauaeO 6eia 6l dynamic cast aflileieOny ia6aa+il programmer, ia6aa+il ё pm a6aa6 nlaa6a3a6u 0 else { enileu5laa6u 66ie6ee-+eaifl eeanna employee производный programmer и воспользоваться им для вызова функции-члена bonus() : Оператор dynamic cast< programmer* >( pe ) приводит свой операнд pe к типу programmer*. Преобразование будет успешным, если pe ссылается на объект типа programmer, и неудачным в противном случае: тогда результатом dynamic cast будет 0. Таким образом, оператор dynamic cast осуществляет сразу две операции. Он проверяет, выполнимо ли запрошенное приведение, и если это так, выполняет его. Проверка производится во время работы программы. dynamic cast безопаснее, чем другие операции приведения типов в C++, поскольку проверяет возможность корректного преобразования. Если в предыдущем примере pe действительно указывает на объект типа programmer, то операция dynamiic cast завершится успешно и pm будет инициализирован указателем на объект типа programmer. В противном случае pm получит значение 0. Проверив значение oid company::payroll( employee *pe ) programmer *pm = dynamic cast< programmer* >( pe ); 11ба1бёаёй1ау 10ёаёа: pm ёпИёйдбаопу аад гбгаабёё 51аа1ёу static int variablePay = 0; variablePay += pm->bonus(); ... объекта класса. Например: Результат, возвращенный dynamic cast, всегда следует проверять, прежде чем использовать в качестве указателя. Более правильное определение функции void company::payroll( employee *pe ) { ай11ё1ё6й dynamic cast ё 1б1аабё6й бадбёйбаб if ( programmer *pm = dynamic cast< programmer* >( pe ) ) { / ёпИёйдгаабй pm аёу айдгаа programer::bonus() else { ёпИёйдгаабй б61ёбёё-ёа1й ёёаппа employee company::payroll() могло бы выглядеть так: Результат операции dynamic cast используется для инициализации переменной pm внутри условного выражения в инструкции if. Это возможно, так как объявления в условиях возвращают значения. Ветвь, соответствующая истинности условия, выполняется, если pm не равно нулю: мы знаем, что операция dynamic cast завершилась успешно и pe указывает на объект programmer. В противном случае результатом объявления будет 0 и выполняется ветвь else. Поскольку теперь оператор и проверка его результата находятся в одной инструкции программы, то невозможно случайно вставить pm, функция company::payroll() может узнать, указывает ли pm на объект programmer. Если это так, то она вызывает функцию-член programmer::bonus () для вычисления премии программисту. Если же dynamiic cast завершается неудачно, то pe указывает на объект типа manager, а значит, необходимо применить более общий алгоритм расчета, не использующий новую функцию-член programmer::bonus() . Оператор dynamic cast употребляется для безопасного приведения указателя на базовый класс к указателю на производный. Такую операцию часто называют понижающим приведением (downcasting). Она применяется, когда необходимо воспользоваться особенностями производного класса, отсутствующими в базовом. Манипулирование объектами производного класса с помощью указателей на базовый обычно происходит автоматически, с помощью виртуальных функций. Однако иногда использовать виртуальные функции невозможно. В таких ситуациях dynamic cast предлагает альтернативное решение, хотя этот механизм в большей степени подвержен ошибкам, чем виртуализация, и должен применяться с осторожностью. Одна из возможных ошибок - это работа с результатом dynamic cast без предварительной проверки на 0: нулевой указатель нельзя использовать для адресации #include <typeinfo> void company::payroll( employee &re ) try { programmer &rm = dynamic cast< programmer & >( enileu5laa6u rm aey aflglaa programmer::bonuE catch ( std::bad cast ) { enileu5laa6u 66ie6ee-+eaifl eeanna employee re ); записать так: случае неудачного завершения ссылочного варианта dynamic cast возбуждается исключение тина bad cast. Класс bad cast определен в стандартной библиотеке; для ссылки на него необходимо включить в программу заголовочный файл <typeinfo>. (Исключения из стандартной библиотеки mi будем рассматривать в следующем разделе.) Когда следует употреблять ссылочный вариант dynamic cast вместо указательного? Это зависит только от желания программиста. При его использовании игнорировать ошибку приведения типа и работать с результатом без проверки (как в указательном варианте) невозможно; с другой стороны, применение исключений увеличивает накладные расходы во время выполнения программы (см. главу 11). какой-либо код между в1нолнением dynamic cast и проверкой, так что pm будет использоваться только тогда, когда содержит правильный указатель. В нред1дущем примере операция dynamiic cast преобразует указатель на базовый класс в указатель на производный. Ее также можно применять для трансформации l-значения типа базового класса в ссылку на тип производного. Синтаксис такого использования dynamiic cast следующий: dynamic cast< Type & >( lval ) где Types - это целевой тин преобразования, а lval - l-значение тина базового класса. Операнд lval успешно приводится к типу Type& только в том случае, когда lval действительно относится к объекту класса, для которого один из производных имеет тип Type. Поскольку нулевых ссылок не бывает (см. раздел 3.6), то проверить успешность выполнения операции путем сравнения результата (т.е. возвращенной оператором dynamic cast ссылки) с нулем невозможно. Если вместо указателей используются ссылки, условие if ( programmer *pm = dynamic cast< programmer* >( pe ) ) нельзя переписать в виде if ( programmer &pm = dynamic cast< programmers >( pe ) ) Для извещения об ошибке в случае приведения к ссылочному типу оператор dynamic cast возбуждает исключение. Следовательно, предыдущий пример можно
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |