Связыватели и адаптеры
Напомним, что для успешной работы вы должны вставить в функцию main тот набор объектов класса Man, который был приведен ранее.
Примечание
При анализе этого кода бросается в глаза неестественность прототипов функций SurName и FirstName. Логика использования этих функций совсем не требует возвращать какое-либо значение, будь то Man, или переменная любого другого типа. Естественным выбором будет прототип void SurNameQ;. Но, к сожалению, этот выбор не проходит по неизвестным мне причинам ни в Visual Studio б, ни в Studio .NET 7.O. Я достаточно много времени потратил на бесполезные поиски ответа на этот вопрос и пришел к выводу, что это ошибка разработчиков. В подтверждение такого вывода приведу следующие аргументы. Во-первых, измените тип возвращаемого значения на любой другой, но не void, и программа будет работать. Например, возьмите прототип string SurName(); и возвращайте return "MicrosoftisOK"; (или другую пару: int и-127). Во-вторых, все примеры на (mem_fun_ref) в документации MSDN возвращают загадочный bool. В-третьих, в документации SGI (Silicon Graphics) приведены аналогичные примеры с функциями, возвращающими void. Там, как вы знаете, используется другая платформа (IRIS). В-четвертых, наш пример (без void) проходит в Visual Studio б и не работает в бета-версии Studio .NET. Будем надеяться, что ситуация со временем выправится.
Адаптер 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) на этапе выполнения. Выбор определяется конкретной ситуацией – типом объекта, попавшим под родительский перст (указатель) в данный момент времени.