абстрагирование от платформы - виртуальный функции

Тема в разделе "LANGS.C", создана пользователем maksim_, 21 янв 2010.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cupuyc

    При том, что при проектировании в зависимости от масштабов использования компонентов нужно выбирать правильные инструменты. Например, чтение конфига - совершенно не performance-critical операция, и делается один раз на старте программы, поэтому АБСОЛЮТНО не важно, какие ресурсы затрачиваются при чтении конфига - хоть распознавание текста из .jpeg-а.

    Pimpl.

    Перечитай еще раз посты. Шаблоны предлагаю не я. Я как раз против.

    Pimpl - не шаблон, и ничего наружу из него торчать не будет.
     
  2. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    да не важно сколько будет выполняться. важно что посреди кода программы будет торчать какая-нибудь гадость с дефайнами.
    _DEN_ тебе адресовано только твоё утверждение о количестве объектов. что касается pimpl - беру свои слова обратно. вкурил.
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Также для тех, кто боится лишнего оверхеда в виде одного call, следует напомнить, что почти всегда платформно-зависимые сущности, скрытые за платформно-независимым интерфейсом, не имеют CopyConstructible семантики, в связи с чем их наследуют от boost::noncopyable и заворачивают в boost::shared_ptr. А там, знаете ли, еще один new, еще один уровень косвенности, и, (о ужас!) счетчик ссылок на интерлокедах, делающий инкремент или декремент на каждый чих! Бида-бида!
     
  4. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Нет, все не надо, в одном месте typedef, или играть дефолтным параметро шаблона, или завернуть new в производящую функцию, или... любой из вариантов, что _все_равно_ придется делать в pimpl ;)

    Возвращаемся к моему первому посту: "pImpl овехед".
    Теперь мне понятно, кто виноват в неискоренимой ненависти к оверхеду в С++. Ты нарушаешь базовый принцип "не платить за неиспользуемое". Сравни свой огород с #6, теперь ответь, нах это все? CRTP по сути тож лишнее, разве что навигацию по коду упростит.
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Возвращаемся к моему первому ответу на твой первый пост: при link-time кодогенерации оверхеда не будет :)

    Твой CRTP по сути решает задачу концепта, и не более. Просто пытается следить за тем, чтобы классы следовали определенному интерфейсу. Но платформно-зависимый код тем не менее торчит наружу. Оверхеда в pimpl не больше чем в crtp - за окном 2010 год и компиляторы уже далеко не Turbo C++ 1.0. Огород - это у тебя. Разберись для начала в вопросах применения CRTP и Pimpl в реальной жизни, меньше будешь глупостей советовать.
     
  6. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Кормя троллей, я что-то сильно отвлекся. Попробую по-порядку. Шаблоны, в частности CRTP и traits, были затронуты поскольку в теме упомянут полиморфизм динамический, который в задаче смысла не имеет. Как пища для размышлений было показано, что есть еще и статический, более модный что ли :) В это надо немного вникнуть, если всю жизнь до этого пользовать абстрактные классы то наверно не сразу получится. Потом даже как грил DEN "можно просто написать N классов и инклудить нужный в зависимости от платформы". Или разнести классы по неймспейсам и сделать ОДИН using. В такие детали опасно лезть, не зная что там еще кроме CTimer это приведет лишь к спорам.
    Ты в здравом уме утверждаешь, что создание не автоматического экземпляра, а в куче - отсутствие оверхеда? :) Да количество создаваемых объектов ни при чем, ты просто забрал у пользователя возможность выбора, возможность не платить за неиспользуемое, насрал в душу идеям Страуструпа :)
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Ну тоесть не будет оверхеда на внешнюю обертку. Внутренняя, естественно, будет работать по указателю. То есть код будет эквивалентен работе с обычным классом по указателю.

    Ах-ах, бедные дети Страуструпа. Прежде чем срать кирпичами из-за дного указателя, неплохо бы ознакомиться с тем, как проектируется и программируется современный софт, и где и на чем следует заострять внимание.
     
  8. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    зачем тогда шаблон, всё равно нужен "С стайл" с его ифдефами?

    я не могу понять чем это:
    #if CURRENT_PLATFORM == _X86_
    class CTimer
    {
    // реализация для x86
    };
    #elif CURRENT_PLATFORM == _X86_64_
    class CTimer
    {
    // реализация для x86-64
    };
    #endif
    хуже вот этого:
    Код (Text):
    1. class CTimerImpl<class ...>
    2. {
    3. };
    4. #if CURRENT_PLATFORM == _X86_
    5. typedef CTimerImpl<A> CTimer;
    6. #elif CURRENT_PLATFORM == _X86_64_
    7. typedef CTimerImpl<B> CTimer
    8. #endif
    и там и сям "с стайл".
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    *бедные идеи :)))
     
  10. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Ты забыл обосновать, зачем _обязывать_ пользователя работать по указателю ;)
    Давай, гуру, просвети же школоту. Но учти, я читал у классиков о неработоспособности водопада. ;)

    Возьмем конкретный пример, Виндовый Хендл.
     
  11. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    В первом варианте class CTimer в каждом файле может иметь разный интерфейс, разработчика ограничивают только соглашения. Шаблон выполняет роль формализатора. Подчеркну, это не идеальное и не единственное решение, но прежде чем двигаться дальше, нужно понять зачем каждая фишка. За один день на форуме это не реально, нужно некоторое время на изучение, смотреть того же Саттера, как пишут другие люди в той же ATL и boost, и ты сам обретешь просветление. В начальном вопросе слишком мало данных, что бы дать единственно верный ответ, как бы DEN не твердил про pimpl, эта фишка - в основном - для уменьшения времени компиляции больших проектов =)

    Код (Text):
    1. // это один файл
    2. class CTimerImpl<class ...>
    3. {
    4. };
    5.  
    6. // а это другой
    7. #if CURRENT_PLATFORM == _X86_
    8. typedef CTimerImpl<A> CTimer;
    9. #elif CURRENT_PLATFORM == _X86_64_
    10. typedef CTimerImpl<B> CTimer
    11. #endif
    В альтернативном варианте все в одном файле. Можно разделить, в #ifdef будут #include, но средства навигации по коду будут путаться в многочистенных CTimer.
     
  12. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    Лично я всегда пытаюсь избегать решений compile-time задач путём введения run-time сущностей. Во многих случаях это, конечно, крохоборство, но тем не менее... так и до C# недалеко. :derisive:
    Выбирая стратегию pImpl для данной задачи, вы вводите фиксированный оверхед для всех системнозависимых объектов. А ведь реализации многих из них могут быть размером порядка size_t (т.е. содержать что-то типа HANDLE), в этом случае относительный оверхед по памяти будет 100%. То же касается оверхеда по производительности (из-за динамического выделения) для лёгких объектов.

    Статический полиморфизм непосредственно задачи отвязки от платформы не решает, но позволяет эффективно (т.е. без runtime оверхеда - виртуальных вызовов) вынести общую логику системнозависимых реализаций в базовый шаблонный класс.

    Не вижу ничего плохого в коде типа:

    typedef PLATFORM_NAME::Object Object;
     
  13. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    При динамической аллокации не только оверхед по скорости, а еще и возможность получить bad_alloc, получаем оверхед по времени разработки ;)
     
  14. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
  15. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    продолжим как протрезвеешь?
     
  16. letopisec

    letopisec New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    228
    cupuyc

    А чем тебе совет qqwe не нравится? Хедеры для классов обычно от платформы не зависят, а .cpp реализации ты выбираешь в зависимости от платформы в makefile.
     
  17. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    letopisec
     
  18. letopisec

    letopisec New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    228
    А то что
    предложил это не эффективно чтоль?
    Чета не пойму при чем тут полиморфизм :-\. Статический, не статический... Полиморфизм нужен для работы со всеми потомками через интерфейс родителя.

    Мне кажется ты не совсем понял.
    В варианте с мейкфайлами (это не обязательно мейкфайлы, для win32 платформы это может быть например .vcproj) интерфейс класса определен в хедере, а конкретные реализации в .cpp. Овехеда вообще никакого.

    К примеру. есть пресловутый Timer. Интерфейс таймера определяем через хедер:

    include/common/timer.h:
    Код (Text):
    1. #ifndef __TIMER_H__
    2. #define __TIMER_H__
    3. class Timer
    4. {
    5. public:
    6.     void set_time (time_t time);
    7.     time_t get_time ();
    8. };
    9. #endif /* __TIMER_H__ */
    кладем его в include/common/

    cоздаем реализацию для avr
    и кладем его в src/avr

    src/avr/timer.cpp
    Код (Text):
    1. #include <avr/resources.h>
    2. Timer::Timer ()
    3. {
    4.     TIMER0 = 0;
    5. }
    6.  
    7. Timer::set_time(time_t time)
    8. {
    9.     TIMER0 = time;
    10. }
    11.  
    12. Timer::get_time()
    13. {
    14.     return TIMER0;
    15. }
    cоздаем реализацию для ARM7
    и кладем его в src/arm7

    src/arm7/timer.cpp
    Код (Text):
    1. #include <arm/resources.h>
    2.  
    3. Timer::Timer ()
    4. {
    5.     ARM7_TIMER = 0;
    6. }
    7.  
    8. Timer::set_time(time_t time)
    9. {
    10.     ARM7_TIMER = time;
    11. }
    12.  
    13. Timer::get_time()
    14. {
    15.     return ARM7_TIMER;
    16. }
    создаем main

    main.cpp:
    Код (Text):
    1. #include <common/timer.h>
    2.  
    3. int main()
    4. {
    5.     Timer timer;
    6.  
    7.     for (;;)
    8.       timer get_time ()
    9.  
    10.     return 0;
    11. }
    12. // незабудь оставить пустую строчку ;-)
    makefile:
    Код (Text):
    1. SOURCES=\
    2.  src/$(PLAT)/timer.cpp \
    3.  src/main.cpp
    4.  
    5.     all:
    6.         $(CC) $(SOURCES)
    Запуск на компиляцию командой make all CC=gcc-avr PLAT=avr
    Для msvs можно создать проекты которые будут включать исходники из нужных каталогов.

    Существует множество открытых проектов которые используют этот подход (для линукса makefile, для msvs2003 vc7.sln, для msvs2005 vc8.sln итд (кста прикольно только что заметил, если vc набрать в русской раскладке, то получится мс :derisive:)).
     
  19. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    letopisec
    хорошо, конечно. а теперь представь, что каждая реализация класса CTimer имеет какие-то уникальные члены класса и методы. как будет выглядеть хидер? куча #if'ов?
     
  20. Voodoo

    Voodoo New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2003
    Сообщения:
    297
    Адрес:
    Новосибирск
    cupuyc
    это, наверное, противоречит постановке задачи.