什么时候应该显式地编写this->member
类的方法?
什么时候应该显式地编写this->member
类的方法?
Answers:
通常,您不必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>
,对于任何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
}
};
i
可能不存在A
。我可以举个例子吗?
template<> struct A<float> { float x; };
如果在与现有成员同名的方法中声明局部变量,则必须使用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
另一种情况是调用操作员时。例如代替
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));
)
在少数情况下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
当地人使用。
仅当在两个潜在的名称空间中具有相同名称的符号时,才需要使用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->”。
this->
避免琐碎的一种用法(只需给局部变量起一个不同的名字)。this
这个答案甚至都没有提到的所有真正有趣的用途。
这样做的其他用途(正如我在阅读摘要和一半的问题...时所认为的那样),而无视(不好)在其他答案中命名歧义,是如果要转换当前对象,请将其绑定到函数对象中或与指向成员的指针一起使用。
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)();
}
}
希望它有助于显示此功能,而不仅仅是this-> member。
您需要使用this
来消除参数/局部变量和成员变量之间的歧义。
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
我在有效的C ++书中发现了另一个显式使用“ this”指针的有趣案例。
例如,假设您有一个const函数,例如
unsigned String::length() const
您不想为每个调用计算String的长度,因此想像这样将其缓存
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
但这不会编译-您正在const函数中更改对象。
窍门来解决,这需要铸造这对一个非const 此:
String* const nonConstThis = (String* const) this;
然后,您就可以在上面
nonConstThis->lengthInitialized = 1;
length
可变,甚至将其放在嵌套结构中。放弃constness几乎从来不是一个好主意。
const
成员函数更改成员,则应为mutable
。否则,您将使其他维护者的生活变得更加复杂。