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

We can do even better by using a map that associates pointers to type_info objects with a vector of Trash pointers. Since a map requires an ordering predicate, we provide one named TInfoLess that calls type_info::before( ). As we insert Trash pointers into the map, they are associated automatically with their type_info key.

//: C08:Recycle2.cpp

// A Trash Recycler

#include

#include

#include

#include

#include

#include

#include

#include "../purge.h"

using namespace std;

class Trash {

  float wt;

public:

  Trash(float wt) : wt(wt) {}

  virtual float value() const = 0;

  float weight() const { return wt; }

  virtual ~Trash() { cout << "~Trash()\n"; }

};

class Aluminum : public Trash {

  static float val;

public:

  Aluminum(float wt) : Trash(wt) {}

  float value() const { return val; }

  static void value(float newval) {

    val = newval;

  }

};

float Aluminum::val = 1.67;

class Paper : public Trash {

  static float val;

public:

  Paper(float wt) : Trash(wt) {}

  float value() const { return val; }

  static void value(float newval) {

    val = newval;

  }

};

float Paper::val = 0.10;

class Glass : public Trash {

  static float val;

public:

  Glass(float wt) : Trash(wt) {}

  float value() const { return val; }

  static void value(float newval) {

    val = newval;

  }

};

float Glass::val = 0.23;

// Comparator for type_info pointers

struct TInfoLess {

  bool operator()(const type_info* t1, const type_info* t2)

  const {

    return t1->before(*t2);

  }

};

typedef map, TInfoLess>

  TrashMap;

// Sums up the value of the Trash in a bin:

void sumValue(const TrashMap::value_type& p, ostream& os) {

  vector::const_iterator tally = p.second.begin();

  float val = 0;

  while(tally != p.second.end()) {

    val += (*tally)->weight() * (*tally)->value();

    os << "weight of "

       << p.first->name()  // type_info::name()

       << " = " << (*tally)->weight() << endl;

    tally++;

  }

  os << "Total value = " << val << endl;

}

int main() {

  srand(time(0)); // Seed random number generator

  TrashMap bin;

  // Fill up the Trash bin:

  for(int i = 0; i < 30; i++) {

    Trash* tp;

    switch(rand() % 3) {

      case 0 :

        tp = new Aluminum((rand() % 1000)/10.0);

        break;

      case 1 :

        tp = new Paper((rand() % 1000)/10.0);

        break;

      case 2 :

        tp = new Glass((rand() % 1000)/10.0);

        break;

    }

    bin[&typeid(*tp)].push_back(tp);

  }

  // Print sorted results

  for(TrashMap::iterator p = bin.begin();

      p != bin.end(); ++p) {

    sumValue(*p, cout);

    purge(p->second);

  }

} ///:~

We’ve modified sumValue( ) to call type_info::name( ) directly, since the type_info object is now available there as the first member of the TrashMap::value_type pair. This avoids the extra call to typeid to get the name of the type of Trash being processed that was necessary in the previous version of this program.

<p>Mechanism and overhead of RTTI</p>

Typically, RTTI is implemented by placing an additional pointer in a class’s virtual function table. This pointer points to the type_info structure for that particular type. The effect of a typeid( ) expression is quite simple: the virtual function table pointer fetches the type_info pointer, and a reference to the resulting type_info structure is produced. Since this is just a two-pointer dereference operation, it is a constant time operation.

For a dynamic_cast(source_pointer), most cases are quite straightforward: source_pointer’s RTTI information is retrieved, and RTTI information for the type destination* is fetched. A library routine then determines whether source_pointer’s type is of type destination* or a base class of destination*. The pointer it returns may be adjusted because of multiple inheritance if the base type isn’t the first base of the derived class. The situation is (of course) more complicated with multiple inheritance in which a base type may appear more than once in an inheritance hierarchy and virtual base classes are used.

Because the library routine used for dynamic_cast must check through a list of base classes, the overhead for dynamic_cast may be higher than typeid( ) (but of course you get different information, which may be essential to your solution), and it may take more time to discover a base class than a derived class. In addition, dynamic_cast allows you to compare any type to any other type; you aren’t restricted to comparing types within the same hierarchy. This adds extra overhead to the library routine used by dynamic_cast.

<p>Summary</p>
Перейти на страницу:

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

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

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

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

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

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

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

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