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

In the previous example of for_each( ), the return value of the algorithm was ignored. This return value is the function that is passed in to for_each( ). If the function is just a pointer to a function, the return value is not very useful, but if it is a function object, that function object may have internal member data that it uses to accumulate information about all the objects that it sees during for_each( ).

For example, consider a simple model of inventory. Each Inventory object has the type of product it represents (here, single characters will be used for product names), the quantity of that product, and the price of each item:.

//: C06:Inventory.h

#ifndef INVENTORY_H

#define INVENTORY_H

#include

#include

#include

#ifndef _MSC_VER

// Microsoft namespace work-around

using std::rand;

using std::srand;

using std::time;

#endif

class Inventory {

  char item;

  int quantity;

  int value;

public:

  Inventory(char it, int quant, int val)

    : item(it), quantity(quant), value(val) {}

  // Synthesized operator= & copy-constructor OK

  char getItem() const { return item; }

  int getQuantity() const { return quantity; }

  void setQuantity(int q) { quantity = q; }

  int getValue() const { return value; }

  void setValue(int val) { value = val; }

  friend std::ostream& operator<<(

    std::ostream& os, const Inventory& inv) {

    return os << inv.item << ": "

      << "quantity " << inv.quantity

      << ", value " << inv.value;

  }

};

// A generator:

struct InvenGen {

  InvenGen() { srand(time(0)); }

  Inventory operator()() {

    static char c = 'a';

    int q = rand() % 100;

    int v = rand() % 500;

    return Inventory(c++, q, v);

  }

};

#endif // INVENTORY_H ///:~

Member functions get the item name and get and set quantity and value. An operator<< prints the Inventory object to an ostream. A generator creates objects that have sequentially labeled items and random quantities and values.

To find out the total number of items and total value, you can create a function object to use with for_each( ) that has data members to hold the totals:.

//: C06:CalcInventory.cpp

// More use of for_each()

#include "Inventory.h"

#include "PrintSequence.h"

#include

#include

using namespace std;

// To calculate inventory totals:

class InvAccum {

  int quantity;

  int value;

public:

  InvAccum() : quantity(0), value(0) {}

  void operator()(const Inventory& inv) {

    quantity += inv.getQuantity();

    value += inv.getQuantity() * inv.getValue();

  }

  friend ostream&

  operator<<(ostream& os, const InvAccum& ia) {

    return os << "total quantity: "

      << ia.quantity

      << ", total value: " << ia.value;

  }

};

int main() {

  vector vi;

  generate_n(back_inserter(vi), 15, InvenGen());

  print(vi.begin(), vi.end(), "vi");

  InvAccum ia = for_each(vi.begin(),vi.end(),

    InvAccum());

  cout << ia << endl;

} ///:~

InvAccum’s operator( ) takes a single argument, as required by for_each( ). As for_each( ) moves through its range, it takes each object in that range and passes it to InvAccum::operator( ), which performs calculations and saves the result. At the end of this process, for_each( ) returns the InvAccum object that you can then examine; in this case, it is simply printed.

You can do most things to the Inventory objects using for_each( ). For example, for_each( ) can handily increase all the prices by 10%. But you’ll notice that the Inventory objects have no way to change the item value. The programmers who designed Inventory thought this was a good idea. After all, why would you want to change the name of an item? But marketing has decided that they want a "new, improved" look by changing all the item names to uppercase; they’ve done studies and determined that the new names will boost sales (well, marketing has to have something to do …). So for_each( ) will not work here, but transform( ) will:

//: C06:TransformNames.cpp

// More use of transform()

#include

#include

#include

#include "Inventory.h"

#include "PrintSequence.h"

using namespace std;

struct NewImproved {

  Inventory operator()(const Inventory& inv) {

    return Inventory(toupper(inv.getItem()),

      inv.getQuantity(), inv.getValue());

  }

};

int main() {

  vector vi;

  generate_n(back_inserter(vi), 15, InvenGen());

  print(vi.begin(), vi.end(), "vi");

  transform(vi.begin(), vi.end(), vi.begin(),

    NewImproved());

  print(vi.begin(), vi.end(), "vi");

} ///:~

Notice that the resulting range is the same as the input range; that is, the transformation is performed in place.

Now suppose that the sales department needs to generate special price lists with different discounts for each item. The original list must stay the same, and any number of special lists need to be generated. Sales will give you a separate list of discounts for each new list. To solve this problem, we can use the second version of transform( ):

//: C06:SpecialList.cpp

// Using the second version of transform()

#include

#include

#include

#include

#include "Inventory.h"

#include "PrintSequence.h"

using namespace std;

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

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

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

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