#include
using namespace std;
:
class Fish
{
public:
virtual void Swim()
{
cout « "Fish swims in water" « endl;
}
1 0 :
// базовый класс всегда должен иметь виртуальный деструктор
virtual -Fish() {}
};
14:
15: class Tuna: public Fish
344 ЗАНЯТИЕ 13. Операторы приведения
{
public:
void Swim()
{
20:
|
cout « "Tuna swims real fast in the sea" « endl;
|
2 1 :
|
}
|
2 2 :
|
|
void BecomeDinner()
{
cout « "Tuna became dinner in Sushi" « endl;
}
};
28:
class Carp: public Fish
{
public:
void Swim()
{
cout « "Carp swims real slow in the lake" « endl;
}
36:
void Talk()
{
cout « "Carp talked crap" « endl;
}
};
42:
void DetectFishType(Fish* InputFish)
{
Tuna* pIsTuna = dynamic_cast (InputFish);
if (pIsTuna)
{
cout « "Detected Tuna. Making Tuna dinner: " « endl;
pIsTuna->BecomeDinner(); // вызов Tuna::BecomeDinner
}
51:
Carp* plsCarp = dynamic_cast (InputFish);
if(plsCarp)
{
cout « "Detected Carp. Making carp talk: " « endl;
pIsCarp->Talk(); // вызов Carp::Talk
}
58:
cout « "Verifying type using virtualFish::Swim: " « endl;
InputFish->Swim(); //вызоввиртуальной функции Swim
}
62:
int main()
{
Carp myLunch;
Tuna myDinner;
67
DetectFishType(SmyDinner);
cout « endl;
Операторы приведения C++
|
345
|
DetectFishType(&myLunch);
return 0;
73:}
Результат
Detected Tuna. Making Tuna dinner:
Tuna became dinner in Sushi
Verifying type using virtual Fish::Swim:
Tuna swims real fast in the sea
Detected Carp. Making carp talk:
Carp talked crap
Verifying type using virtual Fish::Swim:
Carp swims real slow in the lake
Анализ
Это иерархия классов T u n a , C a r p и F is h , рассматривавш аяся на занятии 10, “Реа лизация наследования”. Напомню, что эти два производных класса не только реализуют виртуальную функцию .Sw im (), но и содержат функцию, специфическую для каждого из типов, а именно T u n a : : B e c o m e D in n e r ( ) и C a r p : : T a lk ( ) . Особенным в этом примере
является то, что, имея экземпляр базового класса F is h * , вы можете динамически обна
ружить, указывает ли этот указатель на объект класса T un a или C a rp . Это динамическое обнаружение или идентификация типа времени выполнения осущ ествляется в функции D e t e c t F is h T y p e (), определенной в строках 43 -61. В строке 45 оператор d y n a m ic _ c a s t используется для проверки характера входного указателя базового класса типа F is h * на тип T u n a * . Если это указатель на тип T un a, оператор возвращ ает допустимый адрес, в противном случае — значение NULL. Следовательно, результат оператора d y n a m ic c a s t всегда должен проверяться на допустимость. После проверки успешности в строке 46 вы знаете, что указатель p I s T u n a указывает на допустимый объект класса T una, и в состоя нии использовать его для вызова функции T u n a : : B e c o m e D in n e r (), как демонстрирует строка 49. С карпом вы используете указатель для вызова функции C a r p : : T a lk (), как демонстрирует строка 56. Перед выходом функция D e t e c t F is h T y p e () осущ ествляет проверку типа, вызвав метод F i s h : : Swim (), который, будучи виртуальным, переадресо вывает вызов методу Swim ( ) , реализованному в классе T un a или C a r p соответственно.
Возвращаемое значение оператора dynamic_cast всегда следует прове рять на допустимость. Когда приведение недопустимо, возвращается значение NULL.
Использование оператора reinterpret_cast
Оператор приведения C++ r e i n t e r p r e t c a s t ближе всех к приведению в стиле С. Он позволяет разработчику приводить один тип объекта к другому, независимо от того, связа ны ли их типы, т.е. он интерпретирует тип с использованием следующего синтаксиса:
346 ЗАНЯТИЕ 13. Операторы приведения
Base * pBase = new Base ();
CUnrelated * pUnrelated = reinterpret_cast(pBase); // Такой код плох, даже когда он компилируется!
Это приведение фактически вынуждает компилятор принять ситуации, которые обыч но не разрешил бы оператор s t a t i c _ c a s t . Он находит применение в определенных низ коуровневых приложениях (таких, как драйверы, например), где данные должны быть пре образованы в простой тип, который может принять интерфейс API (например, некоторые функции API работают только с байтовыми потоками, т.е. u n s ig n e d ch a r* ):
Do'stlaringiz bilan baham: |