【问题标题】:C++ policy based design: Inheritance vs composition基于 C++ 策略的设计:继承与组合
【发布时间】:2019-12-27 15:40:24
【问题描述】:

在 Meeting C++ 2019 上,Jon Kalb 发表了关于模板技术的演讲并提到了策略类。来源见这里:https://youtu.be/MLV4IVc4SwI?t=1815

有问题的有趣代码 sn-p 是:

template<class T, class CheckingPolicy>
struct MyContainer : private CheckingPolicy
{
    ...
}

我经常看到这种类型的设计,我想知道这里的继承是否比组合有任何真正的优势。以我个人的经验,我听说过很多关于优先组合胜过继承范式。所以我编写代码的方式会更像这样:

template<class T, class CheckingPolicy>
struct MyContainer
{
    CheckingPolicy policy;
    ...
}

不会涉及任何虚函数。不过,如果您能分享一些见解,我将不胜感激。我会对内存布局的差异及其影响特别感兴趣。如果CheckingPolicy 没有数据成员,而只有check 方法或重载的调用运算符,会有什么不同吗?

【问题讨论】:

    标签: c++ templates inheritance policy-based-design


    【解决方案1】:

    一个可能的原因:当您从CheckingPolicy 继承时,您可以从empty base class optimization 中受益。

    如果CheckingPolicyempty(即,除了大小为0 的位域之外,它没有非静态数据成员,没有虚函数,没有虚拟基类,也没有非空基类),它不会影响MyContainer 的大小。

    相反,当它是MyContainer的数据成员时,即使CheckingPolicy为空,MyContainer的大小也会增加至少一个字节。至少,由于对齐要求,您可能需要额外的填充字节。

    这就是为什么,例如,在std::vector 的实现中,您可以从分配器中找到 ihnehritance。比如libstdc++的implementation:

    template<typename _Tp, typename _Alloc>
    struct _Vector_base {
        typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
            rebind<_Tp>::other _Tp_alloc_type;
    
        struct _Vector_impl : public _Tp_alloc_type, public _Vector_impl_data { 
            // ...
        };
    
        // ...
    };
    

    无状态分配器(如没有非静态数据成员的CheckingPolicy)不会影响std::vector 的大小。

    在 C++20 中,我们将使用 [[no_unique_address]] 来潜在地解决这个问题:标准布局类型需要空基优化,[[no_unique_address]] 只是一个权限,而不是一个要求。 (感谢 Nicol Bolas 指出这一点。)

    【讨论】:

    • 解决这个问题。可能解决这个问题。与标准布局的 EBO 不同,no_unique_address 无法保证。
    猜你喜欢
    • 1970-01-01
    • 2016-02-20
    • 2011-02-03
    • 2011-09-20
    • 2011-04-06
    • 2014-09-30
    • 1970-01-01
    • 2015-08-16
    • 2011-04-08
    相关资源
    最近更新 更多