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

class Square : public Shape {

public:

  virtual void draw() {

    cout << "Square::Draw()" << endl;

  }

  ~Square() {

    cout << "Square::~Square()" << endl;

  }

};

int main() {

  vector vs;

  vs.push_back(new Circle);

  vs.push_back(new Square);

  for_each(vs.begin(), vs.end(),

    mem_fun(&Shape::draw));

  purge(vs);

} ///:~

The for_each( ) algorithm does just what it sounds like it: it passes each element in a sequence to the function object denoted by its third argument. In this case, we want the function object to wrap one of the member functions of the class itself, and so the function object’s "argument" becomes the pointer to the object that the member function is called for. To produce such a function object, the mem_fun( ) template takes a pointer to a member as its argument. The purge( ) function is just a little something we wrote that calls delete on every element of sequence.

The mem_fun( ) functions are for producing function objects that are called using a pointer to the object that the member function is called for, while mem_fun_ref( ) is used for calling the member function directly for an object. One set of overloads of both mem_fun( ) and mem_fun_ref( ) is for member functions that take zero arguments and one argument, and this is multiplied by two to handle const vs. non-const member functions. However, templates and overloading takes care of sorting all that out; all you need to remember is when to use mem_fun( ) vs. mem_fun_ref( ).

Suppose you have a container of objects (not pointers), and you want to call a member function that takes an argument. The argument you pass should come from a second container of objects. To accomplish this, use the second overloaded form of the transform( ) algorithm:.

//: C06:MemFun2.cpp

// Calling member functions through an object reference

#include

#include

#include

#include

#include

using namespace std;

class Angle {

  int degrees;

public:

  Angle(int deg) : degrees(deg) {}

  int mul(int times) {

    return degrees *= times;

  }

};

int main() {

  vector va;

  for(int i = 0; i < 50; i += 10)

    va.push_back(Angle(i));

  int x[] = { 1, 2, 3, 4, 5 };

  transform(va.begin(), va.end(), x,

    ostream_iterator(cout, " "),

    mem_fun_ref(&Angle::mul));

  cout << endl;

  // Output: 0 20 60 120 200

} ///:~

Because the container is holding objects, mem_fun_ref( ) must be used with the pointer-to-member function. This version of transform( ) takes the start and end point of the first range (where the objects live); the starting point of the second range, which holds the arguments to the member function; the destination iterator, which in this case is standard output; and the function object to call for each object. This function object is created with mem_fun_ref( ) and the desired pointer to member. Notice that the transform( ) and for_each( ) template functions are incomplete; transform( ) requires that the function it calls return a value, and there is no for_each( ) that passes two arguments to the function it calls. Thus, you cannot call a member function that returns void and takes an argument using transform( ) or for_each( ).

Most any member function works with mem_fun_ref( ). You can also use standard library member functions, if your compiler doesn’t add any default arguments beyond the normal arguments specified in the standard.[84] For example, suppose you’d like to read a file and search for blank lines; your compiler may allow you to use the string::empty( ) member function like this:.

//: C06:FindBlanks.cpp

// Demonstrates mem_fun_ref() with string::empty()

#include

#include

#include

#include

#include

#include

#include

#include "../require.h"

using namespace std;

typedef vector::iterator LSI;

int main(int argc, char* argv[]) {

  char* fname = "FindBlanks.cpp";

  if(argc > 1) fname = argv[1];

  ifstream in(fname);

  assure(in, fname);

  vector vs;

  string s;

  while(getline(in, s))

    vs.push_back(s);

  vector cpy = vs; // For testing

  LSI lsi = find_if(vs.begin(), vs.end(),

     mem_fun_ref(&string::empty));

  while(lsi != vs.end()) {

    *lsi = "A BLANK LINE";

    lsi = find_if(vs.begin(), vs.end(),

      mem_fun_ref(&string::empty));

  }

  for(size_t i = 0; i < cpy.size(); i++)

    if(cpy[i].size() == 0)

      assert(vs[i] == "A BLANK LINE");

    else

      assert(vs[i] != "A BLANK LINE");

} ///:~

This example uses find_if( ) to locate the first blank line in the given range using mem_fun_ref( ) with string::empty( ). After the file is opened and read into the vector, the process is repeated to find every blank line in the file. Each time a blank line is found, it is replaced with the characters "A BLANK LINE." All you have to do to accomplish this is dereference the iterator to select the current string.

<p>Writing your own function object adapters</p>
Перейти на страницу:

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

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

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

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

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

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

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

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