Читаем Thinking In C++. Volume 2: Practical Programming полностью

  enum {BASEID = 0};

public:

  virtual ~Security() {}

  virtual bool isA(int 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(s) : 0;

  }

};

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(s) : 0;

  }

};

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(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 isA(int id) {

    return id == BASEID || Super::isA(id);

  }

  static Metal* dynacast(Security* s) {

    return (s->isA(TYPEID)) ?

      static_cast(s) : 0;

  }

};

int main() {

  vector portfolio;

  portfolio.push_back(new Metal);

  portfolio.push_back(new Investment);

  portfolio.push_back(new Bond);

  portfolio.push_back(new Stock);

  for (vector::iterator it =

         portfolio.begin();

       it != portfolio.end(); ++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 << "  it's an Investment\n";

  Metal* mp = Metal::dynacast(sp);

  if(mp) cout << "  it's a Metal too!\n";

  purge(portfolio);

} ///:~

The polymorphic isA( ) function checks to see if its argument is compatible with its type argument (id), which means that either id matches the object’s typeID exactly or that of one of its ancestors in the hierarchy (hence the call to Super::isA( ) in that case). The dynacast( ) function, which is static in each class, calls isA( ) for its pointer argument to check if the cast is valid. If isA( ) returns true, the cast is valid, and a suitably cast pointer is returned. Otherwise, the null pointer is returned, which tells the caller that the cast is not valid, meaning that the original pointer is not pointing to an object compatible with (convertible to) the desired type. All this machinery is necessary to be able to check intermediate casts, such as from a Security pointer that refers to a Metal object to a Investment pointer in the previous example program.[104] 

Although for most programs downcasting is not needed (and indeed is discouraged, since everyday polymorphism solves most problems in object-oriented application programs), the ability to check a cast to a more derived type is important for utility programs such as debuggers, class browsers, and databases. C++ provides such a checked cast with the dynamic_cast operator. The following program is a rewrite of the previous example using dynamic_cast.

//: C08:CheckedCast2.cpp

// Uses RTTI’s dynamic_cast

#include

#include

#include "../purge.h"

using namespace std;

class Security {

public:

  virtual ~Security(){}

};

class Stock : public Security {};

class Bond : public Security {};

class Investment : public Security {

public:

  void special() {

    cout << "special Investment function\n";

  }

};

class Metal : public Investment {};

int main() {

  vector portfolio;

  portfolio.push_back(new Metal);

  portfolio.push_back(new Investment);

  portfolio.push_back(new Bond);

  portfolio.push_back(new Stock);

  for (vector::iterator it =

                    portfolio.begin();

       it != portfolio.end(); ++it) {

    Investment* cm = dynamic_cast(*it);

    if(cm)

      cm->special();

    else

      cout << "not a Investment" << endl;

  }

  cout << "cast from intermediate pointer:\n";

  Security* sp = new Metal;

  Investment* cp = dynamic_cast(sp);

  if(cp) cout << "  it's an Investment\n";

  Metal* mp = dynamic_cast(sp);

  if(mp) cout << "  it's a Metal too!\n";

  purge(portfolio);

} ///:~

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных