Программирование >>  Разработка устойчивых систем 

1 ... 132 133 134 [ 135 ] 136 137 138 ... 196


Security

Metal

stock

Investment

Bond

В следующей программе класс Investment поддерживает дополнительную операцию, которая не поддерживается другими классами, поэтому на стадии выполнения важно знать, ссылается ли на объект Investment указатель на Security, или нет. Чтобы реализовать проверку понижающих преобразований, в каждом классе хранится целочисленный идентификатор, отличающий его от других классов иерархии.

: C08:CheckedCast.cpp

Проверка преобразований типа на стадии выполнения #include <iostream> #include <vector> #include ../purge.h using namespace std:

class Security { protected:

enum {BASEID = 0}: public:

virtual -SecurityО {}

virtual bool isACint id) { return (id == BASEID): }

class Stock : public Security {

typedef Security Super: protected:

enum {OFFSET = 1. TYPEID = BASEID + OFFSET}: public: bool isA(int id) { return id == TYPEID Super::isA(id):

static Stock* dynacast(Security* s) { return (s->isA(TYPEID)) ? static cast<Stock*>(s)

class Bond : public Security {

typedef Security Super: protected:

enum {OFFSET = 2. TYPEID = BASEID + OFFSET}: public: bool isA(int id) { return id == TYPEID Super::isA(id):

static Bond* dynacast(Security* s) { return (s->isA(TYPEID)) ? static cast<Bond*>(s)



class Investment : public Security {

typedef Security Super: protected:

enum {OFFSET = 3. TYPEID = BASEID + OFFSET}: public: bool isA(int id) { return id == BASEID Super::isA(id):

static Investment* dynacast(Security* s) { return (s->isA(TYPEID)) ? static cast<Investment*>(s) : 0:

void special О { cout special Investment function\n :

class Metal : public Investment {

typedef Investment Super; protected:

enum {OFFSET = 4. TYPEID = BASEID + OFFSET}; public: bool isACint id) { return id == BASEID 1 Super::isA(id):

static Metal* dynacast(Security* s) { return (s->isA(TYPEID)) ? static cast<Metal*>(s) : 0:

int mainO { vector<Security*> portfolio; portfolio.push back(new Metal): portfoli0.push back(new Investment): portfolio.push back(new Bond); portfolio.push back(new Stock):

for (vector<Security*>::iterator it = portfolio.begin(); it != portfolio.endO; ++it) { Investment* cm = Investment::dynacast(*it): if(cm)

cm->special(): else

cout not a Investment endl;

cout cast from intermediate pointer:\n : Security* sp = new Metal: Investment* cp = Investment::dynacast(sp): if(cp) cout its an InvestmentVn ; Metal* mp = Metal::dynacast(sp): if(mp) cout its a Metal too!\n : purge(portfolio); } /:-

Полиморфная функция isA() проверяет совместимость своего объекта с аргументом типа (id). Это означает, что id совпадает с typelD самого объекта либо одного из его предков (отсюда и вызов Super::isA()). Функция dynacast(), статическая во



В компиляторах Microsoft поддержку RTTI приходится специально активизировать; по умолчанию она отключена. Для этой цели используется ключ командной строки /GR.

всех классах, проверяет допустимость преобразования, вызывая функцию isA() для своего аргумента-указателя. Если isA() возвращает true, значит, преобразование допустимо, и функция возвращает соответствующим образом преобразованный указатель. В противном случае возвращается нулевой указатель. Он сообщает вызывающей стороне, что преобразование недопустимо, то есть исходный указатель ссылается на объект, несовместимый с нужным типом (и не преобразуемый к нему). Все эти манипуляции нужны для проверки опосредованных преобразований (например, от указателя на Security, ссылающегося на объект Metal, к указателю на Investment из предыдущего примера).

В большинстве программ без понижающего преобразования можно обойтись. Более того, использовать его не рекомендуется, потому что основная часть проблем в объектно-ориентированных приложениях решается при помощи обычного полиморфизма. Тем не менее, возможность проверки допустимости преобразования к производному типу важна для служебных программ, таких как отладчики, средства просмотра классов и баз данных. В С++ такие проверяемые преобразования выполняются оператором dynam1c cast. Следующая программа представляет собой модификацию предыдущего примера с использованием оператора dynamic cast

: COSiSecurity.h #ifndef SECURITY.Н #def1ne SECURITY.Н #i nclude <iostream>

class Security { public: virtual ~Secur1ty(){}

class Stock : public Security {}; class Bond : public Security {}:

class Investment : public Security { public: void special О { std::cout special Investment function std::endl:

class Metal : public Investment {}: #end1f SECURITY H III:-

II: C08:CheckedCast2.cpp

Использование RTTI и dynam1c cast

#1 nclude <vector>

#1 nclude ../purge.h

#1nclude Security.h

using namespace std:

Int mainO { vector<Secur1ty*> portfolio: portfolio.push back(new Metal): portfolio.push back(new Investment): portfol1o.push back(new Bond):



1 ... 132 133 134 [ 135 ] 136 137 138 ... 196

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