Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 97 98 99 [ 100 ] 101 102 103 ... 144


воспользоваться dbp

else {

dynamic cast возвращает такой указатель лишь тогда, когда объект, иа который направлен исходный указатель, действ1ггельно принадлежит специфицированному производному классу. В иротивно.м случае он возвращает 0;

□ оператор typeid для идентификации точного типа объекта при наличии указателя на базовый класс;

□ структура type inf о, позволяющая получить дополнительную информацию, ассоциированную с типом.

При обсуждении RTTI внимание будет уделено преимупюственно указателям.

14.2.1. Зачем нужен механизм RTTI

Допустим, в библиотеке имеется класс dialog box, иптерфейсы которого выражены в терминах объектов этого класса. Я же пользуюсь как dialog box, так и собственным классом dbox w str.

class dialog box : public window { библиотечный класс

. . . public:

virtual int askO ;

...

class dbox w str : public dialog box { мой класс

. . . public:

int ask();

virtual char* get string(); . . .

Когда библиотека или система возврашает .мне указатель на dialog box, как я могу узнать, принадлежит ли на самом деле моему классу dbox w str?

Замечу, что я не могу модифи пировать библиотеку, чтобы ввести в dbox w s t г идентифицирующие признаки. А даже если бы .мог, то не ста.,1 бы, чтобы не думать об этом классе в последующих версиях и об ошибках, которые я те.м самым мог внести в стандартную библиотеку.

14.2.2. Оператор dynamic ca5t

Наивное решение - найти тип объекта, на который имеется указатель, и сравнить его с типом класса dbox w str:

void my fct(dialog box* bp)

if (typeid(*bp) == typeid(dbox w str)) { наивное решение

dbox w str* dbp = (dbox w str*)bp;



Оператор typeid {), которому в качестве операнда передано имя типа, возвращает объект, идентифицирующий этот тип. Если операндом является выражение, typeid {) возвращает объект, который идентифицирует тип объекта, обозначаемого этим выраже1Н1ем. В частности, typeid {*Ьр) возвращает объект, позволяющий програм.мисту задавать вопросы о типе объекта, на который указывает bp. В данном случае нас интересует только, совпадает ли тип этого объекта с типом dbox w s t г.

Это простейший из вопросов, которые можно задать, но, как правило, он некорректен. Спрашиваем-то мы, чтобы узнать, можно ли безопасно воспользоваться той или иной воз.можностью производного класса. А чтобы применить ее, нам нужен указатель на объект этого производного класса. В примере выше мы использовали приведение типа в строке, следующей за проверкой. Но ведь обычно нас интересует, удастся ли безопасно выполнить приведение. Этот запрос можно дать непосредственно, воспользовавшись операторо.м dynamic cast:

void my fct(dialog box* bp) {

if (dbox w str* dbp = dynamic cast<dbox w str*>(bp)) { воспользоваться dbp

else {

работать с *bp, как с обычным диалоговым окном

Оператор dynamic cast<T*> (р) преобразует свой операнд в нужный тип Т*, если *р действительно принадлежит пшу т или типу класса, производного от Т. В противном случае значение dynamic cast<T*> (р) равно 0.

Есть несколько причин для объединения проверки и приведения типа в одну операцию:

□ динамическое приведение не допускает несоответствия между приведением и проверкой;

□ пользуясь данными, которые содержатся в объектах с информацией о типе, можно выполнять приведение к типам, которые не полностью определены в области действия проверки;

□ при тако.м же условии допустимо выполнять приведение от виртуального базового класса к производному (см. раздел 14.2.2.3);

□ статическое приведение типов не дает правильных результатов во всех случаях (см. раздел 14.3.2.1).

В большинстве ситуаций можно обойтись оператором dynamic cast. Думается, что это важнейшая часть механизма RTTI и именно на нее пользователи должны обратить особое внимание.

работать с *Ьр, как с обычным диалоговым окном



Оператор dynamic cast можно использовать и для приведения к ссылочным типам. Если приведение к типу ссылки заканчивается неудачно, возникает исключение bad cast. Напри.мер:

void my fct(dialog box& b) {

dbox w str& db = dynamic cast<dbox w str&>(b); воспользоваться db

Я пользуюсь приведением к ссылке, когда хочу проверить предположение о ее типе и считаю, что ошибочное предположение - это сбой в программе. Если же нужно выбрать один из нескольких возможных вариантов, то использую приведение к указателю и проверяю результат.

Не помню, когда я пришел к выводу, что приведение с проверкой типа - лучший способ идентификации типа во время исполнения, коль скоро в языке есть явная поддержка этого. Данную идею .мне подал кто-то из специалистов ко.мпании Xerox PARC. Предложение заключалось в то.м, чтобы обычные приведения выполняли проверку. Как отмечается в разделе 14.2.2.1, этот вариант сопровождался большими затратами и проблемами с совместимостью, но я осознал, что слегка отличный синтаксис приведения может свести к минимуму неправильное использование, к которому располагает механизм переключения по типу вроде предложения INSPECT в Simula.

14.2.2.1. Синтаксис

Спор о том, как должен выглядеть оператор dynamic cast, имел синтаксические аспекты.

Приведения типов в наибольшей степени провоцируют ошибки при программировании на языке С++. И синтаксически они принадлежат к числу наиболее неудачных особенностей. Естественно, по мере возможности я хотел:

□ устранить приведения вообще;

□ сделать их безопасными;

□ предложить такой синтаксис приведений, который с очевидностью показывал бы, что используется небезопасная информация;

□ предложить альтернативы приведению типов, чтобы не возникало желания прибегать к ним.

Вывод о том, что 3-е и 4-е сочетания реализуемы, а 1-е и 2-е - нет, отражает dynamic cast.

Рассматривая первое сочетание, мы отметили, что ни в каком языке, поддерживающем системное программирование, нельзя полностью отказаться от приведения типов. Определенные его формы нужны даже для эффективной поддержки численных расчетов. Поэтому следовало лишь постараться минимизировать употребление приведений и по возможности безопасно определить их поведение. Исходя из этой предпосылки, мы с Ленковым разработали предложение, в котором унифицировались динамические и статические приведения с использованием



1 ... 97 98 99 [ 100 ] 101 102 103 ... 144

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика