Связыватели и адаптеры * Связывателями
pos = m_Name.find_first_of(string(" "),0);
string name = m_Name.substr(0, pos);
cout « '\n' « name;
return *this;
}
//======== Выделяем фамилию
Man SurName()
{
//======== Ищем последнее вхождение пробела
int pos = m_Name.find_last_of(" "), num = m_Name.length () - pos;
string name = m_Name.substr(pos + 1, num);
cout « '\n' « name; return *this;
}
Вектор заполняется элементами, взятыми из массива а г, и при этом используется метод assign, который стирает весь массив и вновь заполняет его элементами, копируя их из диапазона памяти, задаваемого параметрами. Далее мы показываем, как используется связыватель bind2nd и адаптер члена-функции mem_f un_ref:
void main ()
{
Man ar[] =
{
joy, joe, zoran, тагу, simon, liza, Man("Lina Groves", 19)
};
uint size = sizeof(ar)/sizeof(Man);
vector<Man> men;
men.assign(ar, ar+size);
pr(men,"Man Vector");
//======= Привязка второго аргумента
vector<Man>::iterator p = find_if(men.begin(),
men.end(), bind2nd(less<Man>(), win));
if (p != men.end())
cout « "\nFound a man less than " « win « "\n\t" « *p;
//======= Использование метода класса (mem_fun_ref)
cout « "\n\nMen Names:\n";
for_each (men.begin(), men.end(), mem_fun_ref(&Man::SurName));
cout « "\n\nMen First Names:\n";
for_each (men.begin (), men.end(), mem_fun_ref(&Man::FirstName));
cout « "\n\n";
}
Напомним, что для успешной работы вы должны вставить в функцию main тот набор объектов класса Man, который был приведен ранее.
Адаптер mem_fun в отличие от mem_fun__ref используется с контейнерами, хранящими указатели на объекты, а не сами объекты. Хорошим примером использования mem_f un, в котором иллюстрируется полиморфизм позднего связывания
(late binding polymorphism), является следующий:
//======== Базовый класс. К сожалению, абстрактным
//======= его не позволит сделать контейнер
struct Stud
virtual bool print()
{
cout « "\nl'm a Stud";
return true;
}
};
//===== Производный класс struct GoodStud : public Stud
{
bool print ()
{
cout « "\nl'm a Good Stud";
return true;
}
};
//======= Еще один производный класс
struct BadStud : public Stud
{
bool print ()
{
cout « "XnI'm a Bad Stud";
return true;
}
};
//======= Иллюстрируем полиморфизм в действии
void main () {
//====== Вектор указателей типа Stud*
vector<Stud*> v;
//====== Они могут указывать и на детей
v.push_back (new StudO);
v.push_back (new GoodStudO);
v.push_back(new BadStud(J);
//====== Выбор тела метода происходит поздно
//====== на этапе выполнения
for_each(v.begin(), v.end(), mem_fun(&Stud:: print));
cout <<"\n\n";
}
Конечно же, эта программа выведет:
I'm a Stud
I'm a Good Stud
I'm a Bad Stud
так как mem_fun будет вызвана с помощью указателя типа stud* (на базовый класс) — непременное условие проявления полиморфизма, то есть выбора конкретной версии виртуальной функции (адреса функции из vtable) на этапе выполнения. Выбор определяется конкретной ситуацией — типом объекта, попавшим под родительский перст (указатель) в данный момент времени.