c ++静态多态性/ CRTP,带有访问基class成员的附加模板参数

c++ static polymorphism / CRTP with additional template parameters accessing base class member

我想使用 CRTP 实现静态多态性,并向模板参数添加其他类型。

提供如下场景,如何直接从Derived访问Base成员class?是否可以不指定 Base 的完整类型 class?

#include <iostream>

template<class Derived, class X>
struct Base
{
    void set_a( int a ) { _a = a; }
    protected:
        int _a;
};

template<class X>
struct Derived: public Base<Derived<X>, X>
{
    int get_a( )
    {
        // return Base<Derived<X>,X>::_a; // This works!
        return _a; // error: use of undeclared identifier '_a'
    }
};

struct foo;

int main()
{
    Derived<foo> test;

    auto base_p = static_cast< Base<Derived<foo>, foo>* >( &test );
    base_p->set_a( 42 );

    int a = test.get_a();
    std::cout << a << std::endl;
}

g++5.3.1 / clang++3.8.0 输出:

error: use of undeclared identifier '_a'

您可以在 class 中添加 using 声明:

template<class X>
struct Derived: public Base<Derived<X>, X> {

  using Base<Derived<X>, X>::_a;

  /* ... */

};

不过还是要指定一次。

Derived范围内,_a没有被声明而是被继承,所以你必须写this->_a在基数class中查找或者显式写Base<Derived<X>, X>::_a。后者可以用

导入
using Base<Derived<X>, X>::_a;

Derived.

的定义中

tl;dr

如果写入 this->_athis 会自动向上转换为 Base<Derived<X>, X>* 以匹配内部 operator->.

如果只写_a,则执行unqualified name lookup。非限定名称查找是基于范围的,与继承无关。在您的示例中,_aDerived::get_a 中,因此 _a

中搜索
  • Derived::get_a
  • Derived
  • (文件范围)

没有找到_a,导致编译错误