由于“this”关键字通常是不必要的并且在c ++中被省略,为什么在这个例子中它是必需的?

时间:2016-07-22 22:40:15

标签: c++ templates

我正在尝试实现优先级队列。这是接口类的代码:

template<typename TYPE, typename COMP_FUNCTOR = std::less<TYPE>>
class priority_queue {
public:
    typedef unsigned size_type;

    virtual ~priority_queue() {}    // impleted but does nothing, this is not a pure virtual function

    virtual void fix() = 0;

    /* some other methods*/

protected:
    COMP_FUNCTOR compare;

};

导致问题的代码:

template<typename TYPE, typename COMP_FUNCTOR = std::less<TYPE>>
class sorted_priority_queue : public priority_queue<TYPE, COMP_FUNCTOR> {
public:
    typedef unsigned size_type;

    template<typename InputIterator>
    sorted_priority_queue(InputIterator start, InputIterator end, COMP_FUNCTOR comp = COMP_FUNCTOR());

    /* some other methods*/

private:
    std::vector<TYPE> data;
};

template<typename TYPE, typename COMP_FUNCTOR>
template<typename InputIterator>
sorted_priority_queue<TYPE, COMP_FUNCTOR>::sorted_priority_queue(
    InputIterator start, InputIterator end, COMP_FUNCTOR comp) {
    for(auto it = start; it != end; ++it) {
        data.push_back(*it);
    }
    fix();
    this->compare = comp;  // <--- the line that causes problem
}

当我尝试在最后一行做compare = comp时,它说“使用未声明的标识符'比较'”,我必须声明这个 - &gt;为了访问compare,这是在接口类中定义的受保护成员变量,为什么?谢谢。

1 个答案:

答案 0 :(得分:2)

这与在C ++模板类中执行名称查找的方式有关。实际的机制有点棘手,但实际上,当编译器第一次看到模板类时,它会尝试在不使用模板参数的情况下解析它可以使用的所有名称。在这种情况下,这意味着当它看到名称compare在没有this->前缀的情况下使用时,编译器期望compare引用可以在没有任何模板先验知识的情况下找到的内容参数。不幸的是,在您的情况下,编译器无法在不知道模板参数的情况下找出compare引用的内容,因为compare存储在基类中,这取决于模板参数。因此,在尝试找出compare引用的内容时,它不会查看基类内部,因此会出错。

另一方面,如果显式编写this->compare,编译器知道compare是该类的成员,并将推迟查找它引用的名称,直到模板参数为止实际上是可用的。

这是用于实际出现此类错误的语言中为数不多的几种情况之一,如果您正在访问

,这是一个很好的经验法则
  1. 基类中的东西,
  2. 在模板类中,
  3. 继承取决于模板参数的东西,
  4. 然后您将需要使用this->前缀来避免此问题。