在一个类的方法中,什么情况下应该显式地写出 this->member
?
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
}
};
i
在A
中可能不存在。我可以举个例子吗? - Cam Jacksontemplate<> struct A<float> { float x; };
- Macke如果你在一个方法中声明了一个和现有成员同名的局部变量,那么你将需要使用 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
有几个原因可能需要显式使用 this
指针。
虽然我通常不太喜欢,但我看到其他人使用这个->只是为了从智能感知中获得帮助!
有些情况下必须使用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
表示局部变量。
int ret = 6 * VahHolder<Val>::GetVal();
或者2)在类(而不是函数)中使用 using ValHolder<Val>::GetVal;
,这也使得 GetVal 在依赖上下文中可以进行未限定查找。https://godbolt.org/z/n5PY3j51c - Chris Uzdavinis
一些编码标准使用第二种方法,因为他们声称它可以使代码更易读。
例如:
假设MyClass有一个名为'count'的成员变量
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
除了其他答案中提到的(不好的)命名消歧之外,我在阅读摘要和问题一半时想到的另一个用途是:如果您想转换当前对象,将其绑定到函数对象或使用指向成员的指针。
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;
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)();
}
}
有另一种情况是调用操作符。例如,不要写成
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)
,但这似乎很常见。
const
成员函数(Type(rhs).swap(*this);
是合法和正确的),但是临时对象不能绑定到非const
引用参数(编译器会拒绝swap(Type(rhs));
以及this->swap(Type(rhs));
)。 - Ben Voigt如果你在两个潜在的命名空间中有相同名称的符号,那么你只需要使用这个->。例如:
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->”。
this->
的一个微不足道的用法(只需为本地变量命名即可避免)。所有真正有趣的 this
用法都没有在这个答案中提到。 - cmaster - reinstate monica你需要使用this
来区分参数/局部变量和成员变量。
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
research.att.com/~bs/
çژ°هœ¨هڈکوˆگن؛†stroustrup.com
م€‚و–°é“¾وژ¥وک¯ï¼ڑhttp://www.stroustrup.com/bs_faq2.html#thisم€‚ - GManNickG