我什么时候应该显式使用 `this` 指针?

问题描述 投票:0回答:12

我什么时候应该在方法中显式地写

this->member
一个班?

c++ this
12个回答
149
投票

通常,您不必这样做,

this->
是暗示的。

有时,存在名称歧义,可以使用它来消除类成员和局部变量的歧义。然而,这是一个完全不同的情况,其中明确需要

this->

考虑以下代码:

template<class T>
struct A {
   T i;
};

template<class T>
struct B : A<T> {
    T foo() {
        return this->i; //standard accepted by all compilers 
        //return i; //clang and gcc will fail
        //clang 13.1.6: use of undeclared identifier 'i'
        //gcc 11.3.0: 'i' was not declared in this scope
        //Microsoft C++ Compiler 2019 will accept it
    }

};

int main() {
    B<int> b;
    b.foo();
}

如果省略

this->
,有些编译器不知道如何处理
i
。为了告诉它
i
确实是
A<T>
的成员,对于任何
T
,需要
this->
前缀。

注意:仍然可以通过使用省略

this->
前缀:

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

};

37
投票

如果在方法中声明与现有成员同名的局部变量,则必须使用 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


24
投票

您可能需要显式使用

this
指针有多种原因。

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

9
投票

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


8
投票

在极少数情况下必须使用

this
,而在其他情况下,使用 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


6
投票
    成员变量将被隐藏的地方 局部变量
  1. 如果你只是想要 明确表明您 正在调用实例方法/变量

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

示例:

假设 MyClass 有一个名为“count”的成员变量

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

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)

但这似乎很常见。


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 {}

绑定

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。


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->”。


3
投票
您需要使用

this

 来消除参数/局部变量和成员变量之间的歧义。

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

3
投票

this

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

基于这个目的,我们可以有一些情况只使用

this

指针就可以解决问题。

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

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

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;
    
© www.soinside.com 2019 - 2024. All rights reserved.