c++ - 既然 "this"关键字在 C++ 中通常是不必要的并且被省略,那么为什么在这个例子中它是必需的?

标签 c++ templates

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

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时,它显示“使用未声明的标识符'compare'”,我必须声明this->才能访问compare,它是接口(interface)中定义的 protected 成员变量类,为什么?谢谢。

最佳答案

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

如果您显式编写 this->compare,则编译器知道 compare 是该类的成员,并且会推迟查找它的名称指的是直到模板参数实际可用为止。

这是该语言中实际出现此类错误的少数情况之一,并且作为一个很好的经验法则,如果您正在访问

  1. 基类中的某些内容,
  2. 在模板类中,
  3. 根据模板参数继承某些内容,

那么您将需要使用 this-> 前缀来避免此问题。

关于c++ - 既然 "this"关键字在 C++ 中通常是不必要的并且被省略,那么为什么在这个例子中它是必需的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38536216/

相关文章:

c++ - 组合字符串文字和整数常量

c++ - 如何在 C++ 中将字符串转换为模板化类型

c# - 从内部控件绑定(bind)控件属性

c++ - 模板特化 : C++ templates that only accept certain types (revisited)

c++ - #define 的匹配列表到一个模式

java - 在 64-Win 7 上的 32 位 JVM 中读取 C++ 中的 JNI-ByteBuffer 时发生访问冲突

c++ - 通用 lambda、重载、std::is_invocable 和 SFINAE - GCC 和 Clang 之间的不同行为

c++ - 为什么在使用模板和 stdarg 函数时 float 被提升为 double

c++ - 了解 C++ VK_ 热键组合值

c++ - std::array: `at(-2)`为什么没有警告或错误?