避免继承类模板中公共成员不可见和代码膨胀
面向对象编程依赖于受保护和公共类成员的继承。在非模板化环境中,这种继承很简单。然而,在引入类模板时,出现了一个基本问题:基类的公共成员对于派生类模板来说变得不可见。
问题
考虑以下示例:
<code class="cpp">class CBase { public: int Fn1(void) { ... } }; class CDerived : public CBase { public: int FnSum(void) { ... CBase::Fn1(); ... } };</code>
当模板化此代码时,CBase 的 Fn1() 成员从 CDerived 的角度消失:
<code class="cpp">template<unsigned int BYTES> class CBase { public: int Fn1(void) { ... } }; template<unsigned int BYTES> class CDerived : public CBase<BYTES> { public: int FnSum(void) { ... Fn1(); ... } // Error: Fn1 not found! };</code>
解决方案
有多种解决方案可以解决此问题:
解决方案 1(详细前缀):
<code class="cpp">int FnSum(void) { return CBase<BYTES>::Fn1() + CBase<BYTES>::Fn2() + CBase<BYTES>::Arr[0]; }</code>
但是,这种方法在引用多个成员时会导致过多的代码膨胀。
解决方案 2(详细的“this->”前缀):
<code class="cpp">int FnSum(void) { return this->Fn1() + this->Fn2() + this->Arr[0]; }</code>
与解决方案 1 类似,但稍微简洁一些。
解决方案 3(使用语句):
<code class="cpp">using CBase<BYTES>::Arr; using CBase<BYTES>::Fn1; using CBase<BYTES>::Fn2;</code>
这允许直接访问 CBase 成员,无需额外前缀。
解决方案 4(宽容模式):
<code class="cpp">// Compiler flags: /permissive- (MSVC), -fpermissive (GCC/Cl), -fno-implicit-templates (Clang)</code>
禁用严格的 C 合规性,解决了问题,但可能会引入可移植性问题。
更好的解决方案
虽然解决方案 3 是比其他的更干净,它仍然需要重复的“使用”语句。宏可以简化这一点:
<code class="cpp">#include <boost/preprocessor.hpp> #define USING_ONE(r, base, member) using base::member; #define USING_ALL(base, ...) BOOST_PP_SEQ_FOR_EACH(USING_ONE, base, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) #define USING_CBASE(param) USING_ALL(CBase<param>, Arr, Fn1, Fn2, Fn3, Fn4, Fn5)</code>
在派生类中:
<code class="cpp">USING_CBASE(BYTES); // Makes all mentioned CBase members directly accessible</code>
这种方法显着减少了代码膨胀和重复。
以上是为什么继承类模板时基类的公共成员变得不可见?解决这个问题的方法是什么?的详细内容。更多信息请关注PHP中文网其他相关文章!