flo*_*wit 6 c++ inheritance templates policy-based-design
在 Meeting C++ 2019 上,Jon Kalb 发表了关于模板技术的演讲,并提到了策略类。来源见这里:https : //youtu.be/MLV4IVc4SwI?t=1815
有问题的有趣代码片段是:
template<class T, class CheckingPolicy>
struct MyContainer : private CheckingPolicy
{
...
}
Run Code Online (Sandbox Code Playgroud)
我经常看到这种类型的设计,我想知道这里的继承是否比组合有任何真正的优势。在我的个人经验中,我听说过很多关于优先组合而不是继承范式的内容。所以我写代码的方式更像是这样:
template<class T, class CheckingPolicy>
struct MyContainer
{
CheckingPolicy policy;
...
}
Run Code Online (Sandbox Code Playgroud)
不会涉及任何虚拟功能。不过,如果您能分享一些见解,我将不胜感激。我对内存布局的差异及其影响特别感兴趣。如果CheckingPolicy没有数据成员,而只有check方法或重载的调用运算符,会有所不同吗?
一个可能的原因是:当您继承自 时,您可以从空基类优化CheckingPolicy中受益。
如果CheckingPolicy为空(即,除了大小为 的位字段之外,它没有非静态数据成员0、没有虚函数、没有虚拟基类以及没有非空基类),则它不会影响 的大小MyContainer。
相反,当它是 的数据成员时MyContainer,即使为CheckingPolicy空, 的大小MyContainer也会增加至少一个字节。至少,因为由于对齐要求,您可能会有额外的填充字节。
这就是为什么,例如,在实现中,std::vector您可以从分配器中找到 ihnehritance。例如,libstdc++ 的实现:
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 {
// ...
};
// ...
};
Run Code Online (Sandbox Code Playgroud)
无状态分配器(如CheckingPolicy没有非静态数据成员)不会影响 的std::vector大小。
在 C++20 中,我们必须[[no_unique_address]]潜在地解决这个问题:虽然标准布局类型需要空基优化,但这[[no_unique_address]]只是一个许可,而不是一个要求。(感谢尼可波拉斯指出了这一点。)