我最近在一些类中遇到了这个奇怪的函数:
void* getThis() {return this;}
在后面的代码中,它有时是这样使用的:bla->getThis()
(其中bla是指向定义此函数的类的对象的指针)。我似乎不知道这样做有什么好处。是否存在指向对象的指针与对象的this
(其中bla != bla->getThis()
)不同的情况?
这似乎是一个愚蠢的问题,但我想知道我是不是漏掉了什么.
发布于 2013-08-22 06:39:08
当然,指针值可以不同!下面的示例演示了这个问题(您可能需要在您的系统上使用derived1
而不是derived2
来获得差异)。关键是当涉及到虚拟的多重继承时,this
指针通常会进行调整。这可能是一种罕见的情况,但它确实发生了。
这个习惯用法的一个潜在用例是,在将已知类型的对象存储为void const*
(或void*
;const
正确性在这里无关紧要)后,能够恢复这些对象:如果您有一个复杂的继承层次结构,则不能只将任何奇怪的指针转换为void*
,并希望能够将其恢复为原始类型!也就是说,为了容易地获得一个指向base
的指针(从下面的例子中)并将其转换为void*
,你可以调用p->getThis()
,这对static_cast<base*>(p)
来说要容易得多,并获得一个void*
,它可以使用static_cast<base*>(v)
安全地转换为base*
:你可以逆转隐式转换,但前提是你必须转换回原始指针来自的确切类型。也就是说,其中d
是指向从base
派生的类型的对象的指针的static_cast<base*>(static_cast<void*>(d))
是非法的,但static_cast<base*>(d->getThis())
是合法的。
那么,为什么地址一开始就会改变呢?在本例中,base
是两个派生类的虚拟基类,但可能还有更多派生类。其类实际上继承自base
的所有子对象将共享另一个派生类的object中的一个公共base
主题(以下示例中的concrete
)。此base
子对象相对于相应的导出子对象的位置可能不同,具体取决于不同类的排序方式。因此,指向base
对象的指针通常不同于指向虚拟继承自base
的类子对象的指针。如果可能的话,相关的偏移量将在编译时计算,或者在运行时来自vtable之类的东西。当沿着继承层次结构转换指针时,将调整偏移量。
#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';
}
发布于 2013-08-22 07:44:23
您的类可以有自定义的operator&
(因此&a
可能不会返回this
of a
)。这就是std::addressof存在的原因。
发布于 2013-08-22 06:42:44
我在很多年(很多很多年)以前遇到过这样的事情。如果我没记错的话,当一个类操作同一个类的其他实例时,它是需要的。一个例子可能是一个容器类,它可以包含自己的type/( class ?)。
https://stackoverflow.com/questions/18368594
复制相似问题