什么时候应该明确使用`this`指针?

88 c++ this

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

ASk*_*ASk 111

通常,你不必,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();
}
Run Code Online (Sandbox Code Playgroud)

如果省略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
    }

};
Run Code Online (Sandbox Code Playgroud)

  • 很好地使用声明:) (8认同)
  • @CamJackson:可以在类型上专门化类:`template <> struct A <float> {float x; };` (7认同)
  • @PengZhang:Visual Studio 编译器过去常常忽略这些情况下对“this”的需要,这不符合 C++ 标准,请参阅 [Microsoft Docs](https://learn.microsoft.com/de-de/cpp/ build/reference/permissive-standards-conformance?view=vs-2019#look-up-members-in-dependent-base)了解详细信息。 (5认同)
  • 这是一个特别令人讨厌的案例.我以前一直被它咬过. (3认同)
  • 这可能是一个愚蠢的问题,但我不明白为什么`i`可能不存在于'A`中.我可以举一个例子吗? (3认同)

PaV*_*PaV 30

如果在与现有成员同名的方法中声明局部变量,则必须使用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();
}
Run Code Online (Sandbox Code Playgroud)

打印:

5
4

  • 我宁愿避免名称与"​​m_a"或"a_"等惯例冲突. (3认同)

ava*_*kar 18

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

  • 当您想要将对象的引用传递给某个函数时.
  • 当存在与成员对象同名的本地声明的对象时.
  • 当您尝试访问依赖基类的成员时.
  • 有些人更喜欢使用符号来直观地消除代码中成员访问的歧义.


zeb*_*box 6

  1. 成员变量将被局部变量隐藏的位置
  2. 如果您只是想明确表示您正在调用实例方法/变量


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

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

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

   .....
   count++;
   this->count = count;
}
Run Code Online (Sandbox Code Playgroud)


Mac*_*cke 5

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

演员表

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 {}
Run Code Online (Sandbox Code Playgroud)

捆绑

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;
Run Code Online (Sandbox Code Playgroud)

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)();
    }
}
Run Code Online (Sandbox Code Playgroud)

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


rlb*_*ond 5

另一种情况是调用操作员时。例如代替

bool Type::operator!=(const Type& rhs)
{
    return !operator==(rhs);
}
Run Code Online (Sandbox Code Playgroud)

你可以说

bool Type::operator!=(const Type& rhs)
{
    return !(*this == rhs);
}
Run Code Online (Sandbox Code Playgroud)

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

Type& Type::operator=(const Type& rhs)
{
    Type temp(rhs);
    temp.swap(*this);
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么不写,swap(temp)但这似乎很常见。


Bra*_*son 5

尽管我通常并不特别喜欢它,但我已经看到其他人使用this->只是从智能感知中获得帮助!


Joh*_*ing 5

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

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

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

class Foo
{
  Foo& operator=(const Foo& rhs)
  {
    return * this;
  }
};
Run Code Online (Sandbox Code Playgroud)

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

Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Run Code Online (Sandbox Code Playgroud)

有些人认为这很简单,另一些人则认为这很可恶。在后一组算我。

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";
}
Run Code Online (Sandbox Code Playgroud)

4)可用的替代方法:作为编码方式的一部分,用于记录哪些变量是成员变量而不是局部变量。我更喜欢一种不同的命名方案,其中成员变量不能永远与本地变量具有相同的名称。目前,我正在mName为会员和name当地人使用。