Иллюстрированный самоучитель по Visual Studio .NET

Связыватели и адаптеры

Напомним, что для успешной работы вы должны вставить в функцию 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) на этапе выполнения. Выбор определяется конкретной ситуацией – типом объекта, попавшим под родительский перст (указатель) в данный момент времени.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.