this->field vs. this.field in C++

this->field vs. this.field in C++

本文关键字:field this in C++ vs this- gt      更新时间:2023-10-16

鉴于this是一个指针,(2)行和(3)如何在下面的C++类中编译,所以应该需要->符号来访问字段(如第(1)行所示(?(来源(

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
template <typename T>
class sptr_wrapper
{
private:
boost::shared_ptr<T> sptr;
public:
template <typename ...ARGS>
explicit sptr_wrapper(ARGS... a) 
{
this->sptr = boost::make_shared<T>(a...);
}
explicit sptr_wrapper(boost::shared_ptr<T> sptr) 
{
this->sptr = sptr; // (1)
}
virtual ~sptr_wrapper() noexcept = default;
void set_from_sptr(boost::shared_ptr<T> sptr) 
{
this.sptr = sptr; // (2)
}
boost::shared_ptr<T> get_sptr() const
{
return sptr; // (3)
}
};

(2)无效。正如你所说,this是一个指针,我们需要使用->而不是.

作为类模板的成员,sptr_wrapper::set_from_sptr在使用之前不需要实例化。因此,您可以添加一些代码来尝试调用它,然后您可能会像预期的那样收到编译错误。

这适用于类模板的成员:除非在程序中使用该成员,否则不会实例化它,并且不需要定义。


(3)有效;sptr指成员sptr,其效果与this->sptr相同。

在允许 this 关键字的任何上下文(非静态成员函数体、成员初始值设定项

列表、默认成员初始值设定项(中使用非静态类成员成员时,隐式this->将自动添加到名称之前,从而生成成员访问表达式(如果成员是虚拟成员函数,则会导致虚函数调用(。

你会相信这个编译的原因是因为这里没有真正编译任何东西吗?

显示的代码定义了一个模板。

模板在实例化类之前不会变得"真实"。只有到那时,编译器才能仔细查看模板,并尝试计算它正在做的 WTF。

当然,在定义模板时,编译器会半心半意地尝试解析模板,但只能勉强满足自己模板由一些看起来合理的C++代码组成。

如果你在显示的代码中添加一些额外的行,你会得到你渴望的编译错误:

class X {};
void foo()
{
sptr_wrapper<X> x;
boost::shared_ptr<X> y;
x.set_from_sptr(y);
}

这会产生您正在寻找的编译错误:

t.C:27:14: error: request for member ‘sptr’ in ‘(sptr_wrapper<X>*)this’, which is of pointer type ‘sptr_wrapper<X>*’ (maybe you meant to use ‘->’ ?)
27 |         this.sptr = sptr; // (2)

请注意,仅实例化

sptr_wrapper<X> x;

还不够。你必须全力以赴并调用有问题的方法,然后它才会在C++编译器眼中变得"真实",并且它被它窒息。

的确,我可以想到"this.foo"C++代码中可能有效的任何情况,但我确信在构成当前C++标准的 2000 页中的某个地方,正在发生的事情的确切细节以一种非常迂腐的方式详细说明。

你可以考虑在编译器的错误跟踪器上放一个注释,这是一个功能请求,让你的编译器在看到类似的东西时提前发出友好的警告。