gpt4 book ai didi

c++ - 编译时类层次结构的高效配置

转载 作者:可可西里 更新时间:2023-11-01 15:05:28 33 4
gpt4 key购买 nike

这个问题专门针对嵌入式硬实时系统上的 C++ 架构。这意味着大部分数据结构以及确切的程序流在编译时给出,性能很重要并且可以内联大量代码。解决方案最好仅使用 C++03,但也欢迎使用 C++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)

这里,一些类继承自公共(public)基类(例如 Toplevel_A 来自 Toplevel_base),而其他类则根本不需要专门化(例如 Middle_generic)。

目前我能想到的有以下几种做法:

  • (A):如果这是一个常规的桌面应用程序,我会使用虚拟继承并在运行时创建实例,例如使用一个抽象工厂。

    缺点:但是 *_B 类永远不会在产品 A 中使用,因此所有虚函数调用和成员的解引用在运行时不链接到地址会导致相当大的开销。

  • (B) 使用模板特化作为继承机制(例如 CRTP )

    template<class Derived>
    class Toplevel { /* generic stuff ... */ };

    class Toplevel_A : public Toplevel<Toplevel_A> { /* specific stuff ... */ };

    缺点:难以理解。

  • (C):使用不同的匹配文件集并让构建脚本包含正确的文件

    // 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):类似,"Policy based"配置,例如

    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...,只有在所有其他方法都失败的情况下。

是否有任何(其他)已建立的设计模式或更好的解决方案来解决这个问题,以便编译器可以静态分配尽可能多的对象并内联大部分代码,知道正在构建哪个产品和哪些类将被使用?

最佳答案

我会选择 A。在证明这还不够好之前,选择与桌面相同的决策(好吧,当然,在堆栈上分配几千字节,或者使用许多兆字节大的全局变量可能“很明显”它不会起作用)。是的,调用虚函数有一些开销,但我会首先选择最明显和自然的 C++ 解决方案,然后如果它“不够好”则重新设计(显然,尝试尽早确定性能等,并使用像这样的工具一个抽样分析器来确定你把时间花在哪里,而不是“猜测”——事实证明人类是非常糟糕的猜测者)。

如果 A 被证明行不通,我会转向选项 B。这确实不是很明显,但粗略地说,LLVM/Clang 是如何针对硬件和操作系统的组合解决这个问题的,请参阅: https://github.com/llvm-mirror/clang/blob/master/lib/Basic/Targets.cpp

关于c++ - 编译时类层次结构的高效配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29401138/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com