Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет242/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   238   239   240   241   242   243   244   245   ...   256
13.5 Динамическая информация о типе 
Иногда бывает полезно знать истинный тип объекта до его использования в каких-либо операциях
Рассмотрим функцию my(set&) из $$13.3. 
void my_set(set& s) 

for ( T* p = s.first(); p; p = s.next()) { 
// мой код 

// 
... 

Она хороша в общем случае, но представим,- стало известно, что многие параметры множества 
представляют собой объекты типа slist. Возможно также стал известен алгоритм перебора элементов, 
который значительно эффективнее для списков, чем для произвольных множеств. В результате 
эксперимента удалось выяснить, что именно этот перебор является узким местом в системе. Тогда, 


Бьерн Страуструп.
Язык программирования С++ 
 
345 
конечно, имеет смысл учесть в программе отдельно вариант с slist. Допустив возможность определения 
истинного типа параметра, задающего множество, функцию my(set&) можно записать так: 
void my(set& s) 

if (ref_type_info(s) == static_type_info(slist_set)) { 
// сравнение двух представлений типа 
// s 
типа slist 
slist& sl = (slist&)s; 
for (T* p = sl.first(); p; p = sl.next()) { 
// эффективный вариант в расчете на list 


else 

for ( T* p = s.first(); p; p = s.next()) { 
// обычный вариант для произвольного множества 


// 
... 

Как только стал известен конкретный тип slist, стали доступны определенные операции со списками, и 
даже стала возможна реализация основных операций подстановкой. 
Приведенный вариант функции действует отлично, поскольку slist - это конкретный класс, и 
действительно имеет смысл отдельно разбирать вариант, когда параметр является slist_set. 
Рассмотрим теперь такую ситуацию, когда желательно отдельно разбирать вариант как для класса, так 
и для всех его производных классов. Допустим, мы имеем класс dialog_box из $$13.4 и хотим узнать, 
является ли он классом dbox_w_str. Поскольку может существовать много производных классов от 
dbox_w_str, простую проверку на совпадение с ним нельзя считать хорошим решением. Действительно, 
производные классы могут представлять самые разные варианты запроса строки. Например, один 
производный от dbox_w_str класс может предлагать пользователю варианты строк на выбор, другой 
может обеспечить поиск в каталоге и т.д. Значит, нужно проверять и на совпадение со всеми 
производными от dbox_w_str классами. Это так же типично для узловых классов, как проверка на 
вполне определенный тип типична для абстрактных классов, реализуемых конкретными типами. 
void f(dialog_box& db) 

dbox_w_str* dbws = ptr_cast(dbox_w_str, &db); 
if (dbws) { // dbox_w_str 
// здесь можно использовать dbox_w_str::get_string() 

else 

// 
``
обычный'' dialog_box 

// 
... 

Здесь "операция" приведения ptr_cast() свой второй параметр (указатель) приводит к своему первому 
параметру (типу) при условии, что указатель настроен на объект тип, которого совпадает с заданным 
(или является производным классом от заданного типа). Для проверки типа dialog_box используется 
указатель, чтобы после приведения его можно было сравнить с нулем. 
Возможно альтернативное решение с помощью ссылки на dialog_box: 
void g(dialog_box& db) 

try 

dbox_w_str& dbws = ref_cast(dialog_box,db); 
// здесь можно использовать dbox_w_str::get_string() 

catch (Bad_cast) { 


Бьерн Страуструп.
Язык программирования С++ 
 
346 
// 
``
обычный'' dialog_box 

// 
... 

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


Достарыңызбен бөлісу:
1   ...   238   239   240   241   242   243   244   245   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет