为什么我不能使用模板类的父类变量?

时间:2012-04-16 09:00:07

标签: c++ templates inheritance

A.H

template <typename T>
class A
{
    public:
    int a;
}

b.h

template <typename T>
class B : public A<T>
{
   public:
   int f();
}

template <typename T>
int B<T>::f()
{
    int t;
    t = this->a; //Okay
    t = a //Error
    return 0;
}

为什么我不使用this->时会发生错误?

我可以使用某种方法省略this->吗?

(我修正了一些错误)

2 个答案:

答案 0 :(得分:12)

模板实例化有两个阶段(“两阶段名称查找”)。

在第一阶段,解析所有非依赖名称(查找)。在第二阶段,依赖名称得到解决。

依赖名称是依赖于模板参数的名称,例如:

template <typename T>
void foo() {
    x = 0;    // <- Non-dependent, nothing in that refers to "T".
              //    Thus looked up in phase 1, therefore, an 'x' must be
              //    visible.

    T::x = 0; // <- Dependent, because it depends on "T".
              //    Looked up in phase 2, which is when it must be visible.
}

现在,你写道:

t = this->a; //Okay
t = a //Error

这正是我所描述的。在好的术语中,在第2阶段查找t, 因为this取决于模板参数。

在阶段1中查找错误的术语,因为该名称中的任何内容都不依赖于模板参数。 但是在阶段1中,没有a可见,因为编译器无法内省基类模板 在阶段1中,因为模板可以是专用的并且在实例化时, 它可以远离主模板声明,另一个专业化 没有a的,可能是可见的。

示例:

    template <typename T>
    struct Base {
    };


    template <typename T>
    struct Derived : Base<T> {
        void foo() {
            this->a = 0; // As is valid. `this->a` is looked up in phase 2.
        }
    };


    template <> struct Base<int> {
        int a;            
    };


    int main () 
    {
            // The following declarations trigger phase 2 lookup.

            Derived<int>   di;  // valid, because a later specialized
                                // Base<int> is used and all symbols
                                // are resolved.

            Derived<float> df;  // not valid
    }

顺便说一下,我曾经在我的低频博客上写过 this-> is not only a matter of style

答案 1 :(得分:1)

B是一个模板,因此它的名称是非依赖的,因此必须在定义模板时查找,而不是在实例化时查找。但是,在定义模板时,依赖名称是未知的(可能存在目前尚未见过的基类模板A的特化),编译器无法将非限定名称解析为基类。您可以通过this->资格认证将该名称带入当前范围,在其前面添加A<T>::using声明:

template <typename T>
class B : public A<T>
{
   public:
   using A<T>::a;
   int f();
};

另请注意,您在班级声明后遗漏了分号,以及标有// Error评论的行。