什么时候需要使用“this”?

19

在IT技术中,this指针是否必须?如果您需要传递类实例的函数功能,那么您可能需要它。但是在设置/检索/调用/其他成员方面,this一般可选。

我将此标记为C++,因为我的问题是关于这种语言的,但如果有人可以确认在Java和其他使用this指针的面向对象语言中,该结构是否相同,将不胜感激。

3个回答

20

我可以想到三种情况:

当你只是想传递指向当前类的指针时:

class B;
struct A {
    B* parent_;
    A(B* parent) : parent_(parent) {}
};

struct B {
    A* a;
    B() : a(new A(this)) {}
}; 

在构造函数或成员函数中,如果成员被参数遮蔽:
struct A {
    int a;
    void set_a(int a) { this->a = a; }
};

这里,成员变量“a”被参数“a”所遮蔽,因此需要使用this->来访问成员,而不是参数。

(上面的示例被编辑为一个函数,而不是构造函数,因为你通常不会在构造函数中进行赋值)


当访问模板类的基类中的公共/保护成员变量或函数时

template <class T>
struct A {
    int a;
};

template <class T>
struct B : public A<T> {
    int f() { return this->a; }
}

在这里,a本身不是一个依赖名称,因此编译器会期望在B或者不依赖于TB基类中找到它的声明。加上this->使得查找依赖于this类型,并且由于this是一个依赖类型,对a的查找被推迟直到实例化f()

可以写成return A::a而不是return this->a,但是在存在多个基类(直接或间接)的情况下,使用this->更加灵活。这种替代语法也仅限于成员变量和非虚函数 - 如果它与虚函数一起使用,则该函数将直接被调用而不是进行虚函数调用。


1
你可以随时使用classname::variablename来访问它,这样可以用于它,但并非必需。 - PlasmaHH
1
实际上,只有您的第一个示例是正确的,对于另外两个示例,使用this是可选的。在您的第二个示例中,使用构造函数初始化列表是C++的惯用法,并且不会出现歧义问题,例如A::A(int a) : a(a) {}是有效且不会产生歧义(至少对于编译器而言)。 - Andreas Magnusson
2
对于#3,也可以要求使用this,即如果要调用虚成员函数。然后C :: f()this->f()可能不等价。 - Philipp
1
@AndrewLazarus我建议你忽略与Andreas的整个对话。很抱歉没有做出结论,但似乎这些问题太琐碎了,而且我很无聊。我认为我比其他人更广泛地解释了这个问题,并且风格上的问题也被卷入其中。这个问题并不是关于什么是“更好”的,所以在这里你不可能得到一个有用的讨论。 - je4d
3
关于 A<T>::base_function()this->base_function() 的问题,两种方式都可以使用,选择哪一种取决于你希望表达的意思。通常情况下,使用 this-> 更直接,可以解决相关名称的依赖问题。但是使用 A<T>:: 也有其它影响:它不会首先在 B 中查找名为 base_function 的函数,并且即使 base_function 是虚函数,也不会调用虚分派。 - je4d
显示剩余10条评论

15

当局部变量与成员变量同名时,您需要使用它。在这种情况下,局部变量被称为遮蔽成员变量。在这种情况下,您必须使用this才能访问成员变量。

有些人认为始终使用this明确指出正在修改的变量是成员变量是好习惯,但并非总是如此。


对于C ++,您的最后考虑是正确的,但对于Java或C#,这并不总是惯例。 - Geoffroy
这就是为什么你总是要将成员变量的命名与本地变量区分开来,例如 m_myVarmyVar_ 等等。由于使用 this 并不是强制性的,大多数项目选择强制规定成员变量的命名标准。 - Andreas Magnusson
1
我不认为每次都使用this是一个好习惯。只有在存在变量名遮蔽的情况下才使用它。通常也可以避免使用遮蔽变量名。 - Peter Wood
在这种情况下,严格来说并不是必需的,因为您也可以使用“classname::variable”来表达。 - PlasmaHH
@Oleksi - 我也在想是否使用 this 是一个好的习惯。我猜这里有一些争议哈哈。感谢你的有益回答。 - prelic

-4
有时候需要使用 "this",比如当你将对象传递给另一个函数时。 看一下这个 C# 代码(用于打开一个具有此父级的模态窗体)。
Form1 f = new Form();
f.ShowDialog(this);

1
这看起来不像是C++。 - svick
问题是关于C++的。 - ruohola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接