关键字“this”的实际含义是什么?
我有两个与C++相关的问题:
在许多教科书中,关键字this
是指向调用对象的指针。正确的?
由于我喜欢编码,所以我编写了以下简单的代码:
struct Base
{
void g();
virtual void f();
};
void Base::f() {
cout << "Base::f()" << endl;
}
void Base::g() {
cout << "Base::g()" << endl;
cout << "sizeof(*this) : " << sizeof(*this) << endl;
this->f();
}
struct Derived : public Base
{
int d;
void f();
};
void Derived::f()
{
cout << "Derived::f()" << endl;
}
int main()
{
Base a;
Derived b;
cout << "sizeof(a) : " << sizeof(a) << endl;
cout << "sizeof(b) : " << sizeof(b) << endl;
a.g();
b.g();
}
上面的代码产生以下输出:
sizeof(a) : 4
sizeof(b) : 8
Base::g()
sizeof(*this) : 4
Base::f()
Base::g()
sizeof(*this) : 4 // why 4 bytes not 8 bytes?????????
Derived::f()
如果 this
指向调用对象,则 sizeof(* 的第二行应该this)
打印 8 而不是 4,因为调用对象是 b
?这里究竟发生了什么? 这个
已经被降级了吗?!!!
如果 this
已降级为 Base
类型,this->f()
如何调用正确的函数?我真的很困惑。
I have two questions related to C++:
In many textbooks, the keyword this
is a pointer to the calling object. Correct?
As i like to play with coding, i wrote the following simple code:
struct Base
{
void g();
virtual void f();
};
void Base::f() {
cout << "Base::f()" << endl;
}
void Base::g() {
cout << "Base::g()" << endl;
cout << "sizeof(*this) : " << sizeof(*this) << endl;
this->f();
}
struct Derived : public Base
{
int d;
void f();
};
void Derived::f()
{
cout << "Derived::f()" << endl;
}
int main()
{
Base a;
Derived b;
cout << "sizeof(a) : " << sizeof(a) << endl;
cout << "sizeof(b) : " << sizeof(b) << endl;
a.g();
b.g();
}
The above code produces the following output:
sizeof(a) : 4
sizeof(b) : 8
Base::g()
sizeof(*this) : 4
Base::f()
Base::g()
sizeof(*this) : 4 // why 4 bytes not 8 bytes?????????
Derived::f()
If this
is pointing to the calling object, should the second line of sizeof(*this)
print 8 instead of 4 since the calling object is b
? What actually is happening here? Is this
has been demoted?!!!!
If this
has been demoted to type Base
, how this->f()
invokes the correct function? I am really confused.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
需要注意的重要区别是
sizeof
是一个编译时运算符,而不是运行时运算符。编译器将表达式sizeof(*this)
解释为“this
指向的对象的大小”,它在Base::g 的范围内
将是Base
类型的对象。编译器基本上会将该语句重写为如下所示,因为它知道Base
的大小是四个字节:The important distinction that needs to be made is that
sizeof
is a compile-time operator, not a runtime operator. The compiler interprets the expressionsizeof(*this)
as "the size of the object pointed to bythis
", which, in the scope ofBase::g
would be an object of typeBase
. The compiler will essentially rewrite that statement as this, because it knows that the size ofBase
is four bytes:Base
无法查看/访问/了解派生对象的任何部分,因此sizeof
仅报告对其可见的对象部分。更重要的是,Base
方法中的sizeof
无法知道存在或将会有子类(您可以子类化Base
而无需重新编译毕竟),所以除了它所知道的部分之外,它无法报告任何内容。 (sizeof
是在编译时而不是运行时计算的。)Base
can't see/access/know about anything that's part of derived objects, sosizeof
only reports the part of the object that is visible to it. More to the point,sizeof
in a method ofBase
can't know that there are or will be subclasses (you can subclassBase
without recompiling it, after all) so it can't report on anything but the part it knows about. (sizeof
is computed at compile time, not run time.)正确的函数
f
被调用,因为Base::f
是虚拟的。这告诉编译器,当请求调用Base*->f()
时,将在您调用其成员的实际对象的 vtable 中查找被调用者的实际地址。相关
this
的类型是Base*
,这就是为什么sizeof(*this) == sizeof(Base)< /code>,但其 vtable 属于派生对象,因此对
f
的函数调用将进行覆盖。The correct function
f
is called becauseBase::f
is virtual. This tells the compiler that when a call toBase*->f()
is requested, the actual address of the callee is looked up in the vtable of the actual object whose member you invoke.The type of the
this
in question isBase*
, which is whysizeof(*this) == sizeof(Base)
, but its vtable belongs to a derived object and hence the function call tof
goes to the override.this
是一个常量值指针,指向该函数是其非静态成员的对象。这意味着,要使this
成为可行值,它必须仅在类的非静态成员中使用。记住:必须使用对象实例来调用非静态成员函数(instance.function或instance->function);this
是一个指向“实例”的指针。大小永远不是您期望的 8 的原因是因为
g
是类Base
的成员。对于g
,this
的类型为Base *const
,因此*this
的类型为Base& ;
。sizeof(Base)
是4。即使是虚拟成员,这个也不会改变;g
实现的类型始终是Base *const
。实际上重写的版本将具有不同的类型,但只有实现它们的类的类型。this
的类型不遵循多态性;它完全且仅具有定义该函数的类型。this
is a constant value pointer to the object that the function is a non-static member of. Which means that, forthis
to be a viable value, it must be used only in non-static members of a class. Remember: you must use an object instance to call a non-static member function (instance.function or instance->function);this
is a pointer to "instance".The reason the size is never the 8 that you expect is because
g
is a member of the classBase
. Forg
,this
is of typeBase *const
, and therefore*this
is of typeBase&
. Thesizeof(Base)
is 4. Even if it were a virtual member, this would not change; the type for that implementation ofg
would always beBase *const
. Virtually overridden versions would have different types, but only the type of the class that implements them.this
's type does not follow polymorphism; it has exactly and only the type that the function was defined with.