c++ - 在模板派生类中,为什么我需要在成员函数内使用 "this->"限定基类成员名称?

标签 c++ qt templates this name-lookup

当我调查 Qt 的源代码时,我看到 trolltech 人员明确使用 this关键字来访问析构函数上的字段。

inline ~QScopedPointer()
{
    T *oldD = this->d;
    Cleanup::cleanup(oldD);
    this->d = 0;
}

那么,这种用法有什么意义呢?有什么好处吗?

编辑:对于那些投票结束这个问题的人,我怀疑这种用法是用于某些类继承的情况

QScopedPointer class的一部分定义:
template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer

最佳答案

C++ 答案(一般答案)

考虑一个模板类 Derived使用模板基类:

template <typename T>
class Base {
public:
    int d;
};

template <typename T>
class Derived : public Base<T> {
    void f () {
        this->d = 0;
    }
};
this有类型 Derived<T> , 依赖于 T 的类型.所以this有一个依赖类型。所以this->d使 d依赖名称。从属名称在模板定义的上下文中作为非从属名称和在实例化的上下文中进行查找。

this-> ,名称d只会作为非依赖名称进行查找,而不会被找到。

另一种解决方案是声明 d在模板定义本身中:
template <typename T>
class Derived : public Base<T> {
    using Base::d;
    void f () {
        d = 0;
    }
};

Qanswer(具体答案)
dmember of QScopedPointer .它不是继承的成员。 this->这里没有必要。

奥托, QScopedArrayPointer is a template class and d is an inherited member of a template base class:
template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
class QScopedArrayPointer : public QScopedPointer<T, Cleanup>

所以this->有必要here :
inline T &operator[](int i)
{
    return this->d[i];
}

不难看出,直接放this->更容易到处。

了解原因

我想所有 C++ 用户都不清楚为什么在非依赖基类中查找名称而不是在依赖基类中查找名称:
class Base0 {
public:
    int nd;
};

template <typename T>
class Derived2 : 
        public Base0, // non-dependent base
        public Base<T> { // dependent base
    void f () {
        nd; // Base0::b
        d; // lookup of "d" finds nothing

        f (this); // lookup of "f" finds nothing
                  // will find "f" later
    }
};

除了“标准这么说”之外还有一个原因:模板中名称绑定(bind)的工作方式的原因。

当模板被实例化时,模板可以具有后期绑定(bind)的名称:例如 ff (this) .在 Derived2::f() 点定义,没有变量、函数或类型名称 f被编译器知道。 f的已知实体集可以指此时为空。这不是问题,因为编译器知道它会查找 f后来作为函数名,或模板函数名。

OTOH,编译器不知道如何处理 d ;它不是(被调用的)函数名。无法对非(被调用)函数名称进行后期绑定(bind)。

现在,所有这些看起来像是编译时模板多态性的基本知识。真正的问题似乎是:为什么不是 d绑定(bind)到 Base<T>::d在模板定义时?

真正的问题是没有 Base<T>::d在模板定义时,因为 没有完整的类型Base<T>当时:Base<T>已声明,但未定义! 你可能会问:这个怎么办:
template <typename T>
class Base {
public:
    int d;
};

它看起来像一个完整类型的定义!

实际上,在实例化之前,它看起来更像是:
template <typename T>
class Base;

到编译器。不能在类模板中查找名称!但仅限于模板特化(实例化)。模板是做模板特化的工厂,模板不是一组模板特化 .编译器可以查找dBase<T>对于任何特定类型 T ,但它不能
查找 d在类模板Base .直到型T确定,Base<T>::d仍然是抽象的Base<T>::d ;仅当输入 T 时已知,Base<T>::d开始引用 int 类型的变量.

这样做的结果是 类模板 Derived2有一个完整的基类 Base0但是一个不完整的(前向声明的)基类 Base .仅适用于已知类型 T ,“模板类”(类模板的特化)Derived2<T>有一个完整的基类,就像任何普通类一样。

你现在看到:
template <typename T>
class Derived : public Base<T> 

实际上是 基类规范模板 (制作基类规范的工厂)遵循与模板内基类规范不同的规则。

评论:
读者可能已经注意到,我在解释的最后编了几句。

这是非常不同的:这里dDerived<T> 中的限定名称, 和 Derived<T>依赖,因为 T是模板参数。限定名称可以是后期绑定(bind)的,即使它不是(被调用的)函数名称。

另一个解决方案是:
template <typename T>
class Derived : public Base<T> {
    void f () {
        Derived::d = 0; // qualified name
    }
};

这是等价的。

如果你认为Derived<T>里面的定义,治疗Derived<T>有时作为一个已知的完整类,有时作为一个未知的类,有时不一致,好吧,你是对的。

关于c++ - 在模板派生类中,为什么我需要在成员函数内使用 "this->"限定基类成员名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7908248/

相关文章:

c++ - C++ STL vector/列表容器的 Python 等效项

c++ - 模板模板函数定义

python - 图灵完备模板引擎

具有多重继承的 C++ 链表模板?

c++ - 调用 Gtkmm textBuffer->insert 时出现段错误

c++ - C++中名称查找和名称绑定(bind)之间的区别

c++ - 单击上下文菜单项时运行程序

c++ - Qt连接中的Lambda表达式

qt - 从哪里获得 MongoDB Qt 驱动程序

python - 循环中槽位连接少