Шаг 25 - Как сделать виртуальной свободную функцию.
Шаг 25 - Как сделать виртуальной свободную функцию.
Чаще всего этот прием я видел в отношении оператора operator‹‹. Точнее, не чаще, а всегда. На нем и разберем. Пусть у нас есть иерархия классов, и мы хотим определить диагностическую функцию Dump(). Она должна вываливать диагностику в заданное что-то (CDestination). У нас есть два варианта: или сделать функцию виртуальной в иерархии классов:
class CBase {
virtual void Dump(CDestination& ds) = 0;
};
class CFirst: public CBase {
void Dump (CDestination& ds);
};
class CSecond: public CBase {
void Dump (CDestination& ds);
};
Или перегружать ее для каждого класса иерархии или в классе, или в свободной функции:
CDestination {
void Dump (CFirst& fs);
void Dump (CSecond& sc);
};
void Dump (CDestination& ds, CThird& td);
void Dump (CDestination& ds, CFourth& fr);
Ясно, первый вариант предпочтительнее. Во-первых, он обеспечивает полиморфное поведение. Во-вторых, своей диагностикой класс занимается сам, что тоже большой плюс. А второй способ почти невозможен: переписывать класс вывода каждый раз при появлении нового потомка в иерархии нереально (в двойной диспетчеризации дело другое, там просто нет иного выхода); в конце концов, он может быть в купленной библиотеке.
Но у второго варианта есть одно преимущество: функцию Dump() можно обозвать оператором operator‹‹, и это будет выглядеть весьма презентабельно:
// Это декларация
CDestination {
CDestination& operator‹‹ (CFirst& fs);
};
CDestination& operator‹‹ (CDestination& ds, CSecond& sc);
// А это применение
dStream ‹‹ dObject;
Как сделать так, чтобы сохранить замечательное полиморфное поведение первого варианта, и применить эту радость идиота operator‹‹? Легко: пусть operator‹‹ вместо реальной работы просто вызывает виртуальную Dump(). Именно так сделано в MFC - объект afxDump вызывает виртуальную Dump() именно через operator‹‹. (Можно что угодно говорить про Microsoft, но факт есть факт - огромное число полезных и интересных приемов использовано в их продуктах и "… взять их у нее - наша задача!").
#include ‹iostream.h›
class CNoChange;
class CBase {
public:
virtual void passTo (CNoChange& _cb) { cout ‹‹ "base passed" ‹‹ endl; }
};
class CFirst: public CBase {
public:
void passTo (CNoChange& _cb) { cout ‹‹ "first passed" ‹‹ endl; }
};
class CSecond: public CBase {
public:
void passTo (CNoChange& _cb) { cout ‹‹ "second passed" ‹‹ endl; }
};
class CNoChange {
public:
int a;
// Это вариант с оператором - членом класса.
CNoChange& operator‹‹ (CBase& _cb) { _cb.passTo(*this); return *this; }
};
// а это - свободная функция.
//CNoChange& operator‹‹ (CNoChange& _nc, CBase& _cb)
// {_cb.passTo(_nc); return _nc;};
// проверить надо.
int main() {
CNoChange nc;
CFirst fs;
CSecond sc;
nc‹‹fs;
nc‹‹sc;
return 0;
}
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Запуск виртуальной машины
Запуск виртуальной машины Чтобы запустить созданную ВМ, требуется выбрать ее в окне консоли ВМ и щелкнуть на кнопке Start (Пуск).Если выбранные параметры конфигурации ВМ не поддерживаются техническими характеристиками хост-компьютера, то ВМ не запустится, и на экране
Создание виртуальной машины
Создание виртуальной машины Как вы уже знаете, создание виртуальной машины в Parallels Workstation выполняется с помощью мастера. Для его запуска щелкните в нижнем ряду кнопок на кнопке New VM или выберите в меню File одноименную команду.После ознакомления со стартовым окном мастера
Клонирование виртуальной машины
Клонирование виртуальной машины После того как вы сформируете удобную и подходящую для решаемых задач конфигурацию ВМ, можете ее «размножить», используя операцию клонирования ВМ.Чтобы клонировать ВМ, выполните следующие действия.1. Выключите клонируемую ВМ и в
Работа с виртуальной машиной
Работа с виртуальной машиной В общем случае работа с виртуальной машиной начинается с установки гостевой ОС (если в вашем распоряжении нет hdd-файла виртуального диска с установленной ОС). Но еще раньше следует определить, с какого носителя должна производиться
Запуск виртуальной машины
Запуск виртуальной машины Итак, прежде чем произвести первый запуск виртуальной машины, необходимо установить порядок просмотра устройств, с которых может быть произведена загрузка виртуальной системы.В Parallels ввиду того, что утилита BIOS Setup не эмулируется,
function - Создает новую функцию
function - Создает новую функцию functionОпределяет набор операторов, которые вы определили для выполнения определенной задачи. Вы можете декларировать (declare), или определить (define), функцию в том же месте, где вы ее вызываете, или в любом другом месте муви-клипа. При определении
8.15. Эхо-сервер TCP и UDP, использующий функцию select
8.15. Эхо-сервер TCP и UDP, использующий функцию select Теперь мы объединим наш параллельный эхо-сервер TCP из главы 5 и наш последовательный эхо-сервер UDP из данной главы в один сервер, использующий функцию select для мультиплексирования сокетов TCP и UDP. В листинге 8.14 представлена
30.12. Сервер с предварительным порождением потоков: основной поток вызывает функцию accept
30.12. Сервер с предварительным порождением потоков: основной поток вызывает функцию accept Последняя рассматриваемая нами версия сервера устроена следующим образом: главный поток создает пул потоков при запуске сервера, после чего он же вызывает функцию accept и передает
18.4. Создание виртуальной машины
18.4. Создание виртуальной машины Для создания виртуальной машины (для краткости будем иногда писать ВМ) проще воспользоваться мастером конфигурации, но гораздо нагляднее этот процесс происходит при использовании "редактора конфигурации" (рис. 18.2), который запускается
Отклик на единичную функцию
Отклик на единичную функцию Единичная ступенчатая функция показана на рис. 5.20, б. По определению она остается нулевой до t=0, а начиная с этого момента становится равной 1 В. Параметры элементов для схемы, показанной на рис. 5.20, a: R=2 Ом, R1=1 Ом и С=0,125 Ф. Анализ схемы показывает,
R.18.3.4 Приведение указателей на функцию-член
R.18.3.4 Приведение указателей на функцию-член Указатель на функцию-член некоторого объекта можно привести к указателю на какую-то другую функцию, например (int (*) ())p-›f. Результирующий указатель будет настроен на функцию, вызов которой будет происходить с помощью обращения к
56. Обеспечьте бессбойную функцию обмена
56. Обеспечьте бессбойную функцию обмена РезюмеОбычно имеет смысл предоставить для класса функцию swap в целях эффективного и бессбойного обмена внутреннего содержимого объекта с внутренним содержимым другого объекта. Такая функция может пригодиться для реализации ряда
Совет 28. Научитесь использовать функцию base
Совет 28. Научитесь использовать функцию base При вызове функции base для итератора reverse_iterator будет получен «соответствующий» iterator, однако из сказанного совершенно не ясно, что же при этом происходит. В качестве примера рассмотрим следующий фрагмент, который заносит в вектор
7.9.1. Тип указателя на функцию
7.9.1. Тип указателя на функцию Как объявить указатель на функцию? Как выглядит формальный параметр, когда фактическим аргументом является такой указатель? Вот определение функции lexicoCompare(), которая сравнивает две строки лексикографически:#include stringint lexicoCompare( const string sl, const