何时应该明确使用`this`指针?

什么时候应该在类的方法中明确地写this->member

通常情况下,你不必这样做,这是隐含的。

有时,名称不明确,它可以用来消除类成员和局部variables的歧义。 然而,这是一个完全不同的情况,这是明确要求的。

考虑下面的代码:

 template<class T> struct A { int i; }; template<class T> struct B : A<T> { int foo() { return this->i; } }; int main() { B<int> b; b.foo(); } 

如果省略this-> ,编译器不知道如何处理i ,因为它可能存在或不存在于A所有实例中。 为了告诉它, i确实是A<T>的成员,对于任何T ,都需要this->前缀。

注意:通过使用:仍然可以省略this->前缀。

 template<class T> struct B : A<T> { using A<T>::i; // explicitly refer to a variable in the base class int foo() { return i; // i is now known to exist } }; 

如果在与现有成员具有相同名称的方法中声明局部variables,则必须使用this-> var来访问类成员,而不是本地variables。

 #include <iostream> using namespace std; class A { public: int a; void f() { a = 4; int a = 5; cout << a << endl; cout << this->a << endl; } }; int main() { A a; af(); } 

打印:


4

有几个原因可能需要明确使用this指针。

  • 当你想传递你的对象的引用到一些函数。
  • 当存在与成员对象具有相同名称的本地声明对象时。
  • 当您尝试访问从属基类的成员时。
  • 有些人更喜欢使用符号来在视觉上消除其代码中成员访问的歧义。
  1. 成员variables将被局部variables隐藏的地方
  2. 如果你只是想明确地说明你正在调用一个实例方法/variables

一些编码标准使用方法(2),因为他们声称它使代码更容易阅读。

例:
假设MyClass有一个名为“count”的成员variables

 void MyClass::DoSomeStuff(void) { int count = 0; ..... count++; this->count = count; } 

另一种情况是调用操作符时。 例如,而不是

 bool Type::operator!=(const Type& rhs) { return !operator==(rhs); } 

你可以说

 bool Type::operator!=(const Type& rhs) { return !(*this == rhs); } 

这可能更可读。 另一个例子是复制和交换:

 Type& Type::operator=(const Type& rhs) { Type temp(rhs); temp.swap(*this); } 

我不知道为什么它没有写swap(temp)但这似乎是常见的。

虽然我通常不是特别喜欢它,但我已经看到其他人使用这种方法来简单地从intellisense中获得帮助!

有很less的情况下,使用this 必须使用,还有其他的地方使用this指针是解决问题的一种方法。

1) 可用选项 :解决局部variables和类成员之间的歧义, 如@ASk所示 。

2) 否替代:从成员函数返回一个指针或引用。 这经常在重载operator+operator-operator=等时完成(并且应该完成):

 class Foo { Foo& operator=(const Foo& rhs) { return * this; } }; 

这样做可以使用一种称为“ 方法链接 ”的习惯用法,即在一行代码中对对象执行多个操作。 如:

 Student st; st.SetAge (21).SetGender (male).SetClass ("C++ 101"); 

有些人认为这个消费,其他人认为这是一种可憎的行为。 算上我后一组

3) 否替代:解决从属types中的名称。 这在使用模板时会出现,如下例所示:

 #include <iostream> template <typename Val> class ValHolder { private: Val mVal; public: ValHolder (const Val& val) : mVal (val) { } Val& GetVal() { return mVal; } }; template <typename Val> class ValProcessor : public ValHolder <Val> { public: ValProcessor (const Val& val) : ValHolder <Val> (val) { } Val ComputeValue() { // int ret = 2 * GetVal(); // ERROR: No member 'GetVal' int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder) return ret; } }; int main() { ValProcessor <int> proc (42); const int val = proc.ComputeValue(); std::cout << val << "\n"; } 

4) 可选scheme:作为编码风格的一部分,logging哪些variables是成员variables,而不是局部variables。 我更喜欢不同的命名scheme,其中成员varibales永远不能与当地人具有相同的名称。 目前,我正在使用mName作为成员,并为当地人name

你需要使用this来消除参数/局部variables和成员variables之间的歧义。

 class Foo { protected: int myX; public: Foo(int myX) { this->myX = myX; } }; 

如果在两个潜在的命名空间中有相同名称的符号,则只需使用this->。 举个例子:

 class A { public: void setMyVar(int); void doStuff(); private: int myVar; } void A::setMyVar(int myVar) { this->myVar = myVar; // <- Interesting point in the code } void A::doStuff() { int myVar = ::calculateSomething(); this->myVar = myVar; // <- Interesting point in the code } 

在代码的有趣的地方,引用myVar将引用本地(参数或variables)myVar。 为了访问也称为myVar的类成员,你需要明确地使用“this->”。

其他用途(如我以为当我阅读摘要和一半的问题…),无视(坏)命名消歧在其他答案,如果你想转换当前对象,将其绑定到一个函数对象或者通过指向成员来使用它。

types转换

 void Foo::bar() { misc_nonconst_stuff(); const Foo* const_this = this; const_this->bar(); // calls const version dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance } void Foo::bar() const {} 

捆绑

 void Foo::baz() { for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1)); for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); }); } void Foo::framboozle(StuffUnit& su) {} std::vector<StuffUnit> m_stuff; 

PTR到构件

 void Foo::boz() { bez(&Foo::bar); bez(&Foo::baz); } void Foo::bez(void (Foo::*func_ptr)()) { for (int i=0; i<3; ++i) { (this->*func_ptr)(); } } 

希望它有助于显示其他用途,而不仅仅是this-> member。

有人在说this应该是一个参考,我完全同意。 我只想说,预编译器的一个丑陋的线可以模拟:

 #define self (*this) 

不要使用这个:-)

我在Effective C ++书中发现了另外一个显式使用“this”指针的有趣例子。

例如,假设你有一个const函数

  unsigned String::length() const 

你不想为每个调用计算String的长度,所以你想caching它做类似的事情

  unsigned String::length() const { if(!lengthInitialized) { length = strlen(data); lengthInitialized = 1; } } 

但是这不会编译 – 你正在改变const函数中的对象。

解决这个问题的技巧要求将转换为非const的:

  String* const nonConstThis = (String* const) this; 

然后,你可以在上面做

  nonConstThis->lengthInitialized = 1; 

this指针的主要目标(或者我可以说唯一的目的)是指向用于调用成员函数的对象。

基于这个目的,我们可以有一些情况,只有使用this指针才能解决问题。

例如,我们必须返回成员函数中的调用对象,其参数是一个相同的类对象:

 class human { ... human & human::compare(human & h){ if (condition) return h; // argument object else return *this; // invoking object } };