可以'this'指针不同于对象的指针吗? [英] Can 'this' pointer be different than the object's pointer?

查看:114
本文介绍了可以'this'指针不同于对象的指针吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在一些类中遇到了这个奇怪的函数:

I've recently came across this strange function in some class:

void* getThis() {return this;}

后来在代码中有时使用像这样: bla- ; getThis()(其中 bla 是指向这个函数定义的类的对象的指针)
我似乎无法意识到这可以是好的。是否有任何情况下指向一个对象的指针将不同于对象的 this (其中 bla!= bla-> getThis code>)?

And later in the code it is sometimes used like so: bla->getThis() (Where bla is a pointer to an object of the class where this function is defined.) And I can't seem to realize what this can be good for. Is there any situation where a pointer to an object would be different than the object's this (where bla != bla->getThis())?

这似乎是一个愚蠢的问题,但我想知道我是否在这里缺少一些东西。

It seems like a stupid question but I wonder if I'm missing something here..

推荐答案

当然,指针值可以不同!下面的例子演示了这个问题(你可能需要使用 derived1 而不是 derived2 )。关键是当涉及到虚拟的多重继承时, this 指针通常会被调整。这可能是一种罕见的情况,但它发生。

Of course, the pointer values can be different! Below an example which demonstrates the issue (you may need to use derived1 on your system instead of derived2 to get a difference). The point is that the this pointer typically gets adjusted when virtual, multiple inheritance is involved. This may be a rare case but it happens.

这个成语的一个潜在的用例是能够恢复已知类型的对象,存储为 void const * (或 void * ; const 正确性在这里):如果你有一个复杂的继承层次结构,你不能只是转换任何奇怪的指针到 void * ,希望能够恢复到它的原始类型!也就是说,为了容易地获得例如指向 base (从下面的例子)的指针,并将其转换为 void * ,你会调用 p-> getThis()这很容易 static_cast< base *>(p)并获得一个 void * ,它可以安全地转换为 base * c> static_cast< base *>(v):你可以逆转隐式转换,但只有当你转换回原始指针来自的确切类型。也就是说, static_cast< base *>(static_cast< void *>(d))其中 d 指向从 base 派生的类型的对象的指针是非法的,但 static_cast< base *>(d-> getThis())是合法的。

One potential use case of this idiom is to be able to restore objects of a known type after storing them as void const* (or void*; the const correctness doesn't matter here): if you have a complex inheritance hierarchy, you can't just cast any odd pointer to a void* and hope to be able to restore it to its original type! That is, to easily obtain, e.g., a pointer to base (from the example below) and convert it to void*, you'd call p->getThis() which is a lot easier to static_cast<base*>(p) and get a void* which can be safely cast to a base* using a static_cast<base*>(v): you can reverse the implicit conversion but only if you cast back to the exact type where the original pointer came from. That is, static_cast<base*>(static_cast<void*>(d)) where d is a pointer to an object of a type derived from base is illegal but static_cast<base*>(d->getThis()) is legal.

现在,为什么地址会改变?在示例中 base 是两个派生类的虚拟基类,但可能有更多。其类实际上继承自 base 的所有子对象将在另一个派生类的对象中共享一个共同的基本主题( concrete )。这个 base 子对象的位置可能相对于相应的派生子对象不同,这取决于不同类如何排序。因此,指向 base 对象的指针通常不同于虚拟地继承自 base 。相关的偏移量将在编译时计算,如果可能,或在运行时来自vtable。当沿着继承层次转换指针时,偏移量被调整。

Now, why is the address changing in the first place? In the example base is a virtual base class of two derived classes but there could be more. All subobjects whose class virtually inherits from base will share one common base subject in object of a further derived class (concrete in the example below). The location of this base subobject may be different relative to the respective derived subobject depending on how the different classes are ordered. As a result, the pointer to the base object is generally different from the pointers to the subobjects of classes virtually inheriting from base. The relevant offset will be computed at compile-time, when possible, or come from something like a vtable at run-time. The offsets are adjusted when converting pointers along the inheritance hierarchy.

#include <iostream>

struct base
{
    void const* getThis() const { return this; }
};

struct derived1
    : virtual base
{
    int a;
};

struct derived2
    : virtual base
{
    int b;
};

struct concrete
    : derived1
    , derived2
{
};

int main()
{
    concrete c;
    derived2* d2 = &c;
    void const* dptr = d2;
    void const* gptr = d2->getThis();
    std::cout << "dptr=" << dptr << " gptr=" << gptr << '\n';
}

这篇关于可以'this'指针不同于对象的指针吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆