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

Because it allows you to discover type information from an anonymous polymorphic pointer, RTTI is ripe for misuse by the novice because RTTI may make sense before virtual functions do. For many people coming from a procedural background, it’s difficult not to organize programs into sets of switch statements. They could accomplish this with RTTI and thus lose the important value of polymorphism in code development and maintenance. The intent of C++ is that you use virtual functions throughout your code and that you only use RTTI when you must.

However, using virtual functions as they are intended requires that you have control of the base-class definition because at some point in the extension of your program you may discover the base class doesn’t include the virtual function you need. If the base class comes from a library or is otherwise controlled by someone else, a solution to the problem is RTTI: you can derive a new type and add your extra member function. Elsewhere in the code you can detect your particular type and call that member function. This doesn’t destroy the polymorphism and extensibility of the program, because adding a new type will not require you to hunt for switch statements. However, when you add new code in the main body that requires your new feature, you’ll have to detect your particular type.

Putting a feature in a base class might mean that, for the benefit of one particular class, all the other classes derived from that base require some meaningless stub for a pure virtual function. This makes the interface less clear and annoys those who must redefine pure virtual functions when they derive from that base class.

Finally, RTTI will sometimes solve efficiency problems. If your code uses polymorphism in a nice way, but it turns out that one of your objects reacts to this general-purpose code in a horribly inefficient way, you can pick that type out using RTTI and write case-specific code to improve the efficiency.

<p>A trash recycler</p>

To further illustrate a practical use of RTTI, the following program simulates a trash recycler. Different kinds of "trash" are inserted into a single container and then later sorted according to their dynamic types.

//: C08:Recycle.cpp

// A Trash Recycler

#include

#include

#include

#include

#include

#include "../purge.h"

using namespace std;

class Trash {

  float _weight;

public:

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

  virtual float value() const = 0;

  float weight() const { return _weight; }

  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;

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

template

void sumValue(Container& bin, ostream& os) {

  typename Container::iterator tally =

    bin.begin();

  float val = 0;

  while(tally != bin.end()) {

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

    os << "weight of "

        << typeid(**tally).name()

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

    tally++;

  }

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

}

int main() {

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

  vector bin;

  // Fill up the Trash bin:

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

    switch(rand() % 3) {

      case 0 :

        bin.push_back(new Aluminum((rand() % 1000)/10.0));

        break;

      case 1 :

        bin.push_back(new Paper((rand() % 1000)/10.0));

        break;

      case 2 :

        bin.push_back(new Glass((rand() % 1000)/10.0));

        break;

    }

  // Note: bins hold exact type of object, not base type:

  vector glassBin;

  vector paperBin;

  vector alumBin;

  vector::iterator sorter = bin.begin();

  // Sort the Trash:

  while(sorter != bin.end()) {

    Aluminum* ap =

      dynamic_cast(*sorter);

    Paper* pp =

      dynamic_cast(*sorter);

    Glass* gp =

      dynamic_cast(*sorter);

    if(ap) alumBin.push_back(ap);

    else if(pp) paperBin.push_back(pp);

    else if(gp) glassBin.push_back(gp);

    sorter++;

  }

  sumValue(alumBin, cout);

  sumValue(paperBin, cout);

  sumValue(glassBin, cout);

  sumValue(bin, cout);

  purge(bin);

} ///:~

The nature of this problem is that the trash is thrown unclassified into a single bin, so the specific type information is "lost." But later the specific type information must be recovered to properly sort the trash, and so RTTI is used.

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

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

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

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

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

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

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

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

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