Этот вопрос специально посвящен архитектуре С++ для встроенных, жестких систем реального времени. Это означает, что во время компиляции приводятся большие части структур данных, а также точный программный поток, производительность важна, и много кода может быть встроено. Решения предпочтительно используют только С++ 03, но также приветствуются входы С++ 11.
Я ищу установленные шаблоны проектирования и решения архитектурной проблемы, когда одна и та же база кода должна быть повторно использована для нескольких тесно связанных продуктов, в то время как некоторые части (например, аппаратная абстракция) обязательно будут разными.
Я, скорее всего, окажусь иерархической структурой модулей, инкапсулированных в классы, которые затем могут выглядеть примерно так, предполагая 4 слоя:
Product A Product B
Toplevel_A Toplevel_B (different for A and B, but with common parts)
Middle_generic Middle_generic (same for A and B)
Sub_generic Sub_generic (same for A and B)
Hardware_A Hardware_B (different for A and B)
Здесь некоторые классы наследуют от общего базового класса (например, Toplevel_A
от Toplevel_base
), в то время как другим не требуется специализироваться вообще (например, Middle_generic
).
В настоящее время я могу думать о следующих подходах:
-
(A). Если это было обычное настольное приложение, я бы использовал виртуальное наследование и создавал экземпляры во время выполнения, используя, например, Аннотация Factory.
Недостаток. Однако классы
*_B
никогда не будут использоваться в продукте A и, следовательно, разыменование всех вызовов виртуальных функций и членов, не связанных с адресом во время выполнения, приведет к довольно некоторые накладные расходы. -
(B) Использование специализированной специализации в качестве механизма наследования (например, CRTP)
template<class Derived> class Toplevel { /* generic stuff ... */ }; class Toplevel_A : public Toplevel<Toplevel_A> { /* specific stuff ... */ };
Недостаток: трудно понять.
-
(C): используйте разные наборы совпадающих файлов и пусть скрипты build содержат правильный
// common/toplevel_base.h class Toplevel_base { /* ... */ }; // product_A/toplevel.h class Toplevel : Toplevel_base { /* ... */ }; // product_B/toplevel.h class Toplevel : Toplevel_base { /* ... */ }; // build_script.A compiler -Icommon -Iproduct_A
Недостаток. Сложность, сложность в обслуживании и тестировании.
-
(D): один большой файл typedef (или #define)
//typedef_A.h typedef Toplevel_A Toplevel_to_be_used; typedef Hardware_A Hardware_to_be_used; // etc. // sub_generic.h class sub_generic { Hardware_to_be_used the_hardware; // etc. };
Недостаток. Один файл должен быть включен везде и все еще нужен другой механизм, чтобы фактически переключаться между различными конфигурациями.
-
(E): аналогичная, "политическая" настройка, например
template <class Policy> class Toplevel { Middle_generic<Policy> the_middle; // ... }; // ... template <class Policy> class Sub_generic { class Policy::Hardware_to_be_used the_hardware; // ... }; // used as class Policy_A { typedef Hardware_A Hardware_to_be_used; }; Toplevel<Policy_A> the_toplevel;
Недостаток: теперь все шаблоны; много кода нужно перекомпилировать каждый раз.
-
(F): компилятор и препроцессор
// sub_generic.h class Sub_generic { #if PRODUCT_IS_A Hardware_A _hardware; #endif #if PRODUCT_IS_B Hardware_B _hardware; #endif };
Недостаток: Brrr..., только если все остальное не работает.
Есть ли какой-либо (другой) установленный шаблон проектирования или лучшее решение этой проблемы, так что компилятор может статически распределять как можно больше объектов и встроенных больших частей кода, зная, какой продукт строится и какие классы будут использоваться?