0

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

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

#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'
4

2 回答 2

1

你可以在你的类中添加一个using声明:

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

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

  /* ... */

};

不过,您仍然必须指定一次。

于 2016-07-13T12:24:59.457 回答
0

Derived范围内,_a不是声明而是继承,因此您必须编写this->_a以在基类中查找或显式编写Base<Derived<X>, X>::_a. 后者可以用

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

在 的定义中Derived

tl;博士

如果this->_a被写入,this则自动向上转换Base<Derived<X>, X>*以匹配内在的operator->.

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

  • Derived::get_a
  • Derived
  • (文件范围)

没有_a找到,这会触发编译错误。

于 2016-10-01T16:05:50.783 回答