【问题标题】:Why can't I use variable of parent class that is template class?为什么我不能使用模板类的父类变量?
【发布时间】:2012-04-16 09:00:06
【问题描述】:

啊。

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-&gt;时会出现错误?

我可以用某种方法省略this-&gt;吗?

(我修正了一些错误)

【问题讨论】:

  • Joachim Pileborg 给了你答案。除此之外,提供的代码还存在其他问题,无法编译。
  • 这是实际代码吗?类定义后没有尾随分号,int B&lt;T&gt;:f() 的范围运算符不正确,并且错误行中没有分号。
  • 哦,这只是打字错误。我修好了。

标签: c++ templates inheritance


【解决方案1】:

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

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

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

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

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

在第 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

【讨论】:

  • 依赖名称是不依赖于模板参数的名称 -> 依赖名称是依赖于模板参数的名称:)
  • @czxyl:发现这个错误将近五年 :D 感谢您的提示 :)
【解决方案2】:

B 是一个模板,因此它的名称是不相关的,因此必须在定义模板时查找,而不是在实例化模板时查找。但是,在定义模板时,依赖名称是未知的(可能有基类模板A 的特化,到目前为止还没有看到),编译器无法将非限定名称解析为基类班级。您可以通过this-&gt; 限定将名称带入当前范围,方法是在其前面加上A&lt;T&gt;::using 声明:

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

另请注意,您在类声明后缺少分号以及标有// Error 注释的行。

【讨论】:

  • "依赖名称未知" -> 这在 C++ 语言中没有意义。名称可能依赖或不依赖,例如对于类型名 T,A&lt;T&gt;::x 是从属名称,x 不是。作为程序员,x 是一个从属名称可能对你来说是有意义的,但从技术上讲,x不是一个从属名称。
  • -1: “它的名字是非依赖的,因此必须查找” -> 这是错误的。可以有依赖的成员名称。示例:ideone.com/zIa7k
  • 对不起,“......依赖名称无法解析(......),这就是为什么编译器无法确定它是在基类中定义的”会更合适.
  • 但恐怕即使这样也不完全正确。微软的编译器曾经这样做过,因为如果名称存在于可见的模板中是可能的,但标准禁止它,因为它可能会抓取不正确的符号(假设您在主模板和专用模板中有一个值成员 'm' ,你有一个类型名'm';使用微软的旧编译器,这会导致错误的程序)。
猜你喜欢
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2011-10-10
  • 2018-06-07
相关资源
最近更新 更多