Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Замена switch-case полиморфизмом

22K
03 апреля 2007 года
deninok
16 / / 01.03.2007
Уважаемые участники форума!

В прекрасной книге "Философия С++" Брюса Эккеля я прочитал рекомендацию о том, что не следует использовать длинные switch-case конструкции. Вместо этого нужно применять полиморфизм и наследование. Вот убейте меня на месте, но я не пойму, как одно можно заменить другим!
Что такое switch-case конструкция? Это реализация выбора некоторого кода (из имеющегося списка) в соответствии с некоторым однозначно интерпретируемым критерием. Когда мы имеем дело с полиморфными вызовами функций классов наследников, используя при этом общий интерфейс (то есть класс-родитель), то здесь тоже наблюдается идея выбора кода (например, переопределенной функции) из некоторого множества. Но ведь в switch-case конструкции критерием является значение некоторой переменной (так чаще всего), а в случае с полиморфизмом критерием является тип!
Может быть, я, будучи новичком в С++, чего-то просто не понимаю? Не могли бы вы привести хотя бы примитивные примеры, как можно заменить первое вторым. Буду очень признателен.
355
03 апреля 2007 года
<SCORP>
786 / / 21.10.2006
http://w8.platonoff.com/refactoring/page35.xtp
http://forum.exler.ru/index.php?showtopic=115776 и ссылки в ответах посотреть
502
03 апреля 2007 года
Jail
550 / / 30.01.2007
[LEFT]Ага))) Тем то и отличается объектно-ориентированное программирование от функционального :)
Поглядите книжечку Стефана Дэвиса "С++ for Dumies", там хорошо и доступным языком расписано, что такое объекты и принципы ООП подхода и их различия между функциональным программирование.
[/LEFT]
22K
04 апреля 2007 года
deninok
16 / / 01.03.2007
To Jail
Что такое объекты и принципы ООП, мне известно. И хотя я начинающий в языке, но уже, в принципе, не чайник. Вот вы заменяли когда-нибудь switch-case конструкцию на полиморфные вызовы функций-наследников от базового интерфейса? Если да, то буду признателен за ваши примеры. Коротко, прямо здесь, на форуме.
502
04 апреля 2007 года
Jail
550 / / 30.01.2007
[LEFT]Если честно, то не заменял. Но мне достаточно доступного интерфейса класса, защищённых членов класса, Friend' ов связанных списков, полиморфных вызовов функций, компоновки всей этой каши в одно целое и т.д. и т.п. :D
Я вобще очень редко (если опять таки честно) применяю конструкции case, считаю что возможно обойтись и без них, думаю эта конструкция хоть и используется в С++, но всё же(это моё мнение) она изжила себя и просто мигрировала из С))))
Я больше как-то использую Java...хм...и сами подумайте..ведь в Java как-то люди обходятся без case))))

[/LEFT]
240
05 апреля 2007 года
aks
2.5K / / 14.07.2006
Цитата: Jail

Я больше как-то использую Java...хм...и сами подумайте..ведь в Java как-то люди обходятся без case))))


=)))))))))))
Ты что этим хотел сказать, что в Java нет конструкции switch/case абсолютно такой же как и в C/C++?

502
05 апреля 2007 года
Jail
550 / / 30.01.2007
[LEFT]
Цитата:
=)))))))))))
Ты что этим хотел сказать, что в Java нет конструкции switch/case абсолютно такой же как и в C/C++?


Я лично хотел сказать что она нафиг не нужна, вот и всё (это чисто по Русски)))). Блин, aks не придерайся к словам, а....
Или ты видел код на Java перенасыщенный конструкциями switch/case????
Продемонстрируй плиз))))) Очень хочу поглядеть :)
[/LEFT]

240
06 апреля 2007 года
aks
2.5K / / 14.07.2006
Не перенасыщенный, но активно применяющийся в случае необходимости видел неоднократно. Корпоративный закрытый код я конечно демонстрировать не буду, сам понимаешь наверно почему. Но полно опенсорсных проектов на яве. Глянь. Вот ссылка например: http://www.osflash.org/red5
=))

И вот тебе простой пример - как ты будешь например определять тип пакета приходящего из какого то внешнего источника (сети, файла, или еще откуд - неважно) у которого тип как раз задается допустим константой идущей в первом байте?
3
06 апреля 2007 года
Green
4.8K / / 20.01.2000
Цитата: aks

И вот тебе простой пример - как ты будешь например определять тип пакета приходящего из какого то внешнего источника (сети, файла, или еще откуд - неважно) у которого тип как раз задается допустим константой идущей в первом байте?


Интересный пример... чтоб показать один из вариантов замены switch/case полиморфизмом. :)

При небольшом количестве вариантов пакетов и нерасширяемой архитектуре switch/case будет вполне нормальным решением.
Но для других случаев больше подойдет архитектура с регистрацией обработчиков (псевдокод):

Код:
class IPacketHandler
{
    TypeID getID() const =0;
    TypeResult handlePacket(cont Packet&) =0;
};

class DataPacketHandler :IPacketHandler
{
    TypeID getID() const { return dataPacketID; }
    TypeResult handlePacket(cont Packet&);
};

class CommandPacketHandler :IPacketHandler
{
    TypeID getID() const { return commandPacketID; }
    TypeResult handlePacket(cont Packet&);
};

class PacketManager
{
    void addPacketHandler(IPacketHandler* handler) {
        handlers.add(handler);
    }

    TypeResult handlePacket(cont Packet& packet) {
        for_each(handlers) {
            if( handler->getID() == packet.id ) {
                return handler.handlePacket(packet);
            }
        }
    }

    Container<IPacketHandler*> handlers;
};

В таких случаях любят делать авторегистрацию, и даже автосоздание обработчика, но я сторонник явного создания и регистрации.
240
06 апреля 2007 года
aks
2.5K / / 14.07.2006
Green, ну обычно да - подобным образом и делается. Если есть какая то большая коллекция классов для разных пакетов. При этом собственно функциональность switch забирается циклическим if-ом.
Но все же когда количество типов строго фиксированное и небольшое то зачастую прощще через switch создавть объект необходимого типа.
273
06 апреля 2007 года
3A3-968M
1.2K / / 22.12.2005
switch-конструкция очень легко заменяется на хэш-таблицу, в которой ключём является case-выражение, а значением - код, выполняющийся при данном значении. Мои размышления на эту тему здесь:
switch vs hashtable
3
06 апреля 2007 года
Green
4.8K / / 20.01.2000
Хеш-таблица - это один из вариантов контейнера (это я применительно к своему примеру). Но вот хранить в этом контейнере IMHO лучше функторы (или др. объекты с единым интерфейсом), а не функции.
273
06 апреля 2007 года
3A3-968M
1.2K / / 22.12.2005
Цитата: Green
Но вот хранить в этом контейнере IMHO лучше функторы (или др. объекты с единым интерфейсом), а не функции.


Это чем же?? Интерфейс требует организации новой структуры, тогда как функцию можно просто передать по ссылке.

3
06 апреля 2007 года
Green
4.8K / / 20.01.2000
Концептульно правильнее.
По большому счету это паттерн "стратегия". Каждая стратегия - отдельная сущность, которую целесообразнее оформлять в отдельный класс.

Ну и расширяемая вешь получается. Можно объединять несколько методов в одном таком классе-обработчике, например, предобработка и пост обработка (я недавно выкладывал HookAPI, там это явно прослеживается), можно хранить состояние обработчика и т.д. Представляется возможность получать информацию об обработчиках, настраивать их. Это нужно для более интеллектуальных менеджеров, например, кодеки: каждый кодек не только обрабатывает поток входных данных, но может и давать информацию о себе об формате входных и выходных данных. Это нужно, к примеру, для построения графов таких кодеков (см. DirectShow и GraphEdit).

Кроме того, засовывать всю обработку в одну функцию на несколько десятков страниц - плохая практика. Разбивать функцию на несколько и плодить при этом глобальные функции - тоже некрасиво. А так есть некоторый класс-обработчик, с четкой самостоятельной структурой и общим интерфейсом. От которого, кстати, можно наследовать другие обработчики.

В принципе вопрос из серии: что лучше callback-функция или объект-обработчик?
502
06 апреля 2007 года
Jail
550 / / 30.01.2007
[LEFT]
Цитата:
В принципе вопрос из серии: что лучше callback-функция или объект-обработчик?

Вот вот...это точно...
Я бы сказал это ещё дело "вкуса" aks и кто какую "стратегию" выбрал для себя. Я всё же бы заменил switch/case , на if/else if/else (ну привык я так). Например, уже давно читал книжечку Дениса Ричи "Язык Си", он там аргументирует (не помню правда агрументов), почему лично он заменяет switch/case на if-else, но так же пишет о "привычке" к такому решению лично его самого. А в других случаях, работа только с объектами и обработчиками при принятия данных в твоём примере. А за ссылочку спасибо, внушает)))
[/LEFT]

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог