2016-07-13 14 views
0

Я хотел бы реализовать статический полиморфизм с использованием CRTP, а также добавить дополнительные типы к параметрам шаблонов.C++ static polymorphism/CRTP с дополнительными параметрами шаблона, обращающимися к члену базового класса

Предоставляя следующий сценарий, как я могу напрямую обращаться к элементам Base из класса Derived? Возможно ли это без указания полного типа базового класса?

#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; 
} 

г ++ 5.3.1/лязг ++ 3.8.0 Выход:

error: use of undeclared identifier '_a' 

ответ

1

Вы можете добавить using декларацию в своем классе:

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

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

    /* ... */ 

}; 

Вы все еще должны укажите его один раз.

+0

Ницца обходной путь! Но я хотел бы понять, почему я должен указать его один раз! – Albert

+1

@Albert Вы должны указать его, потому что ваш базовый класс зависит от параметра шаблона вашего класса. – Holt

+0

Хорошо. Теперь @Holt нашел настоящую проблему, я нашел связанный с ней вопрос: http://stackoverflow.com/questions/1239908/why-doesnt-a-derived-template-class-have-access-to-a-base- шаблон класса-идент – Albert

0

В Derived объеме, _a не объявлена, но по наследству, так что вы должны написать this->_a искать в базовом классе или явно написать Base<Derived<X>, X>::_a. Последние могут быть импортированы с

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

в определении Derived.

Т.Л., др

Если this->_a написано this автоматически до литом для Base<Derived<X>, X>*, чтобы соответствовать внутренней operator->.

Если записано только _a, то выполняется unqualified name lookup. Неквалифицированный поиск имени основан на масштабах, который не связан с наследованием. В вашем примере, _a в Derived::get_a, так _a ищется в

  • Derived::get_a
  • Derived
  • (сфера файла)

Нет _a найден, который вызывает ошибку компиляции.