問題描述
當我調查 Qt 的源代碼時,我看到 trolltech 人員明確使用 this
關鍵字來訪問析構函數上的字段.
While I investigate source code of Qt I saw that trolltech guys explicitly use this
keyword to access a field on destructor.
inline ~QScopedPointer()
{
T *oldD = this->d;
Cleanup::cleanup(oldD);
this->d = 0;
}
那么,這種用法有什么意義呢?有什么好處嗎?
So, what's the point of this usage? Are there any benefits?
對于那些投票結束這個問題的人,我懷疑這種用法是用于某些類繼承的情況
For those who vote for closing this question, I suspect that this usage is for some class inheritance cases
QScopedPointer 類定義的一部分:
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
.所以 this
有一個依賴類型.所以 this->d
使 d
成為依賴名稱.依賴名稱在模板定義的上下文中作為非依賴名稱和實例化上下文進行查找.
this
has type Derived<T>
, a type which depends on T
. So this
has a dependent type. So this->d
makes d
a dependent name. Dependent names are looked-up in the context of the template definition as non-dependent names and in the context of instantiation.
如果沒有 this->
,名稱 d
只會作為非依賴名稱被查找,而不會被找到.
Without this->
, the name d
would only be looked-up as a non-dependent name, and not be found.
另一種解決方案是在模板定義本身中聲明d
:
Another solution is to declare d
in the template definition itself:
template <typename T>
class Derived : public Base<T> {
using Base::d;
void f () {
d = 0;
}
};
Qanswer(具體答案)
d
是 成員QScopedPointer
.它不是繼承的成員.this->
在這里不是必需的.
Qanswer (specific answer)
d
is a member of QScopedPointer
. It isn't an inherited member. this->
is not necessary here.
OTOH,QScopedArrayPointer
是一個模板類,d
是一個模板基類的繼承成員:
OTOH, 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->
是必要的 此處:
inline T &operator[](int i)
{
return this->d[i];
}
很容易看出,將 this->
放在任何地方更容易.
It's easy to see that it's easier to just put this->
everywhere.
我想所有 C++ 用戶都不清楚為什么在非依賴基類中查找名稱而不是在依賴基類中查找名稱:
I guess it isn't clear to all C++ users why names are looked-up in non-dependent base classes but not in dependent base classes:
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
}
};
除了標準這么說"之外還有一個原因:模板中名稱綁定的工作方式.
There is a reason beside "the standard says so": cause of way name binding in templates works.
模板可以具有后期綁定的名稱,當模板被實例化時:例如 f (this)
中的 f
.在Derived2::f()
定義點,編譯器不知道變量、函數或類型名稱f
.f
可以引用的一組已知實體此時是空的.這不是問題,因為編譯器知道它稍后會查找 f
作為函數名或模板函數名.
Templates can have name that are bound late, when the template is instantiated: for example f
in f (this)
. At the point of Derived2::f()
definition, there is no variable, function or type name f
known by the compiler. The set of known entities that f
could refer to is empty at this point. This isn't a problem because the compiler knows it will lookup f
later as a function name, or a template function name.
OTOH,編譯器不知道如何處理d
;它不是(被調用的)函數名.無法對非(被調用)函數名稱進行后期綁定.
OTOH, the compiler doesn't know what to do with d
; it isn't a (called) function name. There is no way to do late binding on non-(called) functions names.
現在,所有這些看起來像是編譯時模板多態的基本知識.真正的問題似乎是:為什么在模板定義時 d
沒有綁定到 Base
?
Now, all of this may seem like elementary knowledge of compile-time template polymorphism. The real question seems to be: why isn't d
bound to Base<T>::d
at template definition time?
真正的問題是在模板定義時沒有Base
,因為沒有完整的類型Base
那個時候:Base
被聲明了,但沒有定義! 你可能會問:那怎么辦:
The real issue is that there is no Base<T>::d
at template definition time, because there is no complete type Base<T>
at that time: Base<T>
is declared, but not defined! You may ask: what about this:
template <typename T>
class Base {
public:
int d;
};
看起來像是一個完整類型的定義!
it looks like the definition of a complete type!
實際上,直到實例化,它看起來更像是:
Actually, until instantiation, it looks more like:
template <typename T>
class Base;
編譯器.不能在類模板中查找名稱!但僅限于模板特化(實例化).模板是使模板特化的工廠,模板不是模板特化的集合.編譯器可以在 Base
中查找任何特定類型的 T
中的 d
,但它不能在類模板Base
中查找d
.在確定類型 T
之前,Base
仍然是抽象的 Base
;只有當類型 T
已知時,Base
才開始引用 int
類型的變量.
to the compiler. A name cannot be looked-up in a class template! But only in a template specialisation (instantiation). The template is a factory to make template specialisation, a template isn't a set of template specialisation. The compiler can lookup d
in Base<T>
for any particular type T
, but it cannot
lookup d
in the class template Base
. Until a type T
is determined, Base<T>::d
remains the abstract Base<T>::d
; only when type T
is known, Base<T>::d
start to refer to a variable of type int
.
這樣做的結果是類模板 Derived2
有一個完整的基類 Base0
但是一個不完整的(前向聲明的)基類 <代碼>基礎代碼>.僅對于已知類型 T
,模板類"(類模板的特化)Derived2
具有完整的基類,就像任何普通類一樣.
The consequence of this is that the class template Derived2
has a complete base class Base0
but an incomplete (forward declared) base class Base
. Only for a known type T
, the "template class" (specialisations of a class template) Derived2<T>
has a complete base classes, just like any normal class.
你現在看到了:
template <typename T>
class Derived : public Base<T>
實際上是一個基類規范模板(一個制作基類規范的工廠),它遵循與模板內的基類規范不同的規則.
is actually a base class specification template (a factory to make base class specifications) that follows different rules from a base class specification inside a template.
備注:讀者可能已經注意到,我在解釋的最后編了幾句.
Remark: The reader may have noticed that I have made-up a few phrases at the end of the explanation.
這是非常不同的:這里d
是Derived
中的限定名,而Derived
是依賴的,因為T
是一個模板參數.限定名稱可以是后期綁定的,即使它不是(被調用的)函數名稱.
This is very different: here d
is a qualified name in Derived<T>
, and Derived<T>
is dependent since T
is a template parameter. A qualified name can be late-bound even if it isn't a (called) function name.
另一種解決方案是:
template <typename T>
class Derived : public Base<T> {
void f () {
Derived::d = 0; // qualified name
}
};
這是等價的.
如果您認為在 Derived
的定義中,將 Derived
視為已知的完整類,有時將其視為未知類有時不一致,嗯,你是對的.
If you think that inside the definition of Derived<T>
, the treatment of Derived<T>
as a known complete class sometimes and as an unknown class some other times in inconsistent, well, you are right.
這篇關于在模板派生類中,為什么我需要使用“this->"來限定基類成員名稱?在成員函數中?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!