Выбрать главу

Приведение типов (из Base* в Base*) реализовано.

В классе Base.

Приведение типов (из Base* в Derived*) не реализовано.

Приведение bр к типу Derived* реализовано, поскольку bр действительно указывает на объект класса Derived.

В классе Derived.

Теперь приведение bр к типу Derived* не реализовано, поскольку bр в действительности указывает на объект класса Base.

Приведение dp к типу Base * реализовано.

В классе Derived.

Оператор dynamic_cast можно иногда использовать вместо оператора typeid. Например, предположим, что класс Base — полиморфный и является базовым для класса Derived, тогда при выполнении следующего фрагмента кода указателю dp будет присвоен адрес объекта, адресуемого указателем bp, но только в том случае, если этот объект действительно является объектом класса Derived.

Base *bp;

Derived *dp;

// . . .

if(typeid(*bp) == typeid(Derived)) dp = (Derived *) bp;

В этом случае используется обычная операция приведения типов. Здесь это вполне безопасно, поскольку инструкция if проверяет законность операции приведения типов с помощью оператора typeid до ее реального выполнения. То же самое можно сделать более эффективно, заменив операторы typeid и инструкцию if оператором

dynamic_cast:

dp = dynamic_cast<Derived *> (bp);

Поскольку оператор dynamic_cast успешно выполняется только в том случае, если объект, подвергаемый операции приведения к типу, уже является объектом либо заданного типа, либо типа, выведенного из заданного, то после завершения этой инструкции указатель dp будет содержать либо нулевое значение, либо указатель на объект типа Derived. Кроме того, поскольку оператор dynamic_cast успешно выполняется только в том случае, если заданная операция приведения типов законна, то в определенных ситуациях ее логику можно упростить. В следующей программе показано, как оператор typeid можно заменить оператором dynamic_cast. Здесь выполняется один и тот же набор операций дважды: с использованием сначала оператора typeid, а затем оператора dynamic_cast.

/* Использование оператора dynamic_cast вместо оператора typeid.

*/

#include <iostream>

#include <typeinfo>

using namespace std;

class Base {

 public:

  virtual void f() {}

};

class Derived : public Base {

 public:

  void derivedOnly() {

   cout << "Это объект класса Derived.\n";

  }

};

int main()

{

 Base *bp, b_ob;

 Derived *dp, d_ob;

 //--------------------------------

 // Использование оператора typeid

 //--------------------------------

 bp = &b_ob;

 if(typeid(*bp) == typeid(Derived)) {

  dp = (Derived *) bp;

  dp->derivedOnly();

 }

 else  cout <<"Операция приведения объекта типа Base к " <<"типу Derived не выполнилась.\n";

 bp = &d_ob;

 if(typeid(*bp) == typeid(Derived)) {

  dp = (Derived *) bp;

  dp->derivedOnly();

 }

 else  cout <<"Ошибка, приведение типа должно " <<"быть реализовано!\n";

 //--------------------------------------

 // Использование оператора dynamic_cast

 //--------------------------------------

 bp = &b_ob;

 dp = dynamic_cast<Derived *> (bp);

 if(dp) dp->derivedOnly();

 else  cout << "Операция приведения объекта типа Base к " <<" типу Derived не выполнилась.\n"; bp = &d_ob;

 dp = dynamic_cast<Derived *> (bp);

 if(dp) dp->derivedOnly();

 else  cout << "Ошибка, приведение типа должно " << "быть реализовано!\n";