117

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

4

12 回答 12

134

通常,您不必这样做,这this->是暗示的。

有时,存在名称歧义,可用于消除类成员和局部变量的歧义。但是,这是一个完全不同的情况,this->明确要求。

考虑以下代码:

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>, 对于 any的成员Tthis->前缀是必需的。

注意:仍然可以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
    }

};
于 2009-06-14T18:12:35.210 回答
34

如果在方法中声明一个与现有成员同名的局部变量,则必须使用 this->var 来访问类成员而不是局部变量。

#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;
    a.f();
}

印刷:

5
4

于 2009-06-14T18:10:39.270 回答
22

this您可能需要显式使用指针有几个原因。

  • 当您想将对对象的引用传递给某个函数时。
  • 当存在与成员对象同名的本地声明对象时。
  • 当您尝试访问依赖基类的成员时。
  • 有些人更喜欢这种表示法,以便在他们的代码中从视觉上消除成员访问的歧义。
于 2009-06-14T18:18:30.607 回答
7

虽然我通常不特别喜欢它,但我看到其他人使用它-> 只是为了从智能感知中获得帮助!

于 2009-06-14T23:29:25.603 回答
7

在少数情况下this 必须使用 using,而在其他情况下使用this指针是解决问题的一种方法。

1)可用的替代方案:解决局部变量和类成员之间的歧义,如 @ASk 所示

2)无选择:this从成员函数返回指针或引用。operator+在重载, operator-,operator=等时经常这样做(并且应该这样做) :

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

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

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

一些人认为这是一种恶行,另一些人则认为它是可憎的。把我算在后一组。

3)无选择:解析依赖类型中的名称。使用模板时会出现这种情况,如下例所示:

#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)可用的替代方案:作为编码风格的一部分,记录哪些变量是成员变量而不是局部变量。我更喜欢不同的命名方案,其中成员变量永远不能与本地人具有相同的名称。目前我正在mName为会员和name当地人使用。

于 2009-06-15T04:32:40.470 回答
6
  1. 成员变量将被局部变量隐藏的位置
  2. 如果您只想明确说明您正在调用实例方法/变量


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

示例:
假设 MyClass 有一个名为 'count' 的成员变量

void MyClass::DoSomeStuff(void)
{
   int count = 0;

   .....
   count++;
   this->count = count;
}
于 2009-06-14T18:13:15.097 回答
5

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

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),但这似乎很常见。

于 2009-06-14T18:24:41.030 回答
4

如果你在两个潜在的命名空间中有一个同名的符号,你只需要使用 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 将引用本地(参数或变量)myVar。为了访问也称为 myVar 的类成员,您需要显式使用“this->”。

于 2009-06-14T18:11:53.043 回答
4

这个的其他用途(正如我在阅读摘要和一半问题时所想的那样......),忽略其他答案中的(坏)命名歧义,如果你想转换当前对象,将它绑定在一个函数对象中或将其与指向成员的指针一起使用。

演员表

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 之外的其他用途。

于 2009-06-14T18:22:11.130 回答
3

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

class Foo
{
protected:
  int myX;

public:
  Foo(int myX)
  {
    this->myX = myX; 
  }
};
于 2009-06-14T18:11:28.830 回答
3

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

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

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

class human {

... 

human & human::compare(human & h){
    if (condition)
        return h;       // argument object
    else 
        return *this;   // invoking object
    }
};
于 2015-09-02T15:09:27.120 回答
2

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

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

  unsigned String::length() const

您不想为每个调用计算字符串的长度,因此您想缓存它做类似的事情

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

但这不会编译 - 您正在更改 const 函数中的对象。

解决这个问题的技巧需要将this转换为非常量this

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

然后,你就可以在上面做

  nonConstThis->lengthInitialized = 1;
于 2009-06-14T18:27:33.707 回答