C++ Can';这';指针不能与对象';什么是指针?
我最近在某个类中遇到了这个奇怪的函数:C++ Can';这';指针不能与对象';什么是指针?,c++,C++,我最近在某个类中遇到了这个奇怪的函数: void* getThis() {return this;} 在后面的代码中,它有时会这样使用:bla->getThis()(其中bla是指向定义此函数的类的对象的指针) 我似乎不知道这有什么好处。是否存在指向对象的指针与对象的this(其中bla!=bla->getThis())不同的情况 这似乎是一个愚蠢的问题,但我想知道我是否遗漏了什么。不。是的,在有限的情况下 这看起来像是受到Smalltalk的启发,在Smalltalk中,所有对象都有一个yo
void* getThis() {return this;}
在后面的代码中,它有时会这样使用:bla->getThis()
(其中bla是指向定义此函数的类的对象的指针)
我似乎不知道这有什么好处。是否存在指向对象的指针与对象的this
(其中bla!=bla->getThis()
)不同的情况
这似乎是一个愚蠢的问题,但我想知道我是否遗漏了什么。不。是的,在有限的情况下
这看起来像是受到Smalltalk的启发,在Smalltalk中,所有对象都有一个yourself
方法。在某些情况下,这可能会使代码更干净。正如注释注释,这看起来是一种奇特的方式,甚至在C++中实现这个习语。
在您的具体案例中,我会询问该方法的实际使用情况,看看它是如何使用的 当然,指针值可以不同!下面的示例演示了该问题(您可能需要在系统上使用
derived1
,而不是derived2
,以获得差异)。关键是当涉及虚拟的多重继承时,这个
指针通常会得到调整。这可能是一个罕见的情况,但它发生了
这个习惯用法的一个潜在使用案例是,在将已知类型的对象存储为void-const*
(或void*
;此处的const
正确性无关紧要)之后,能够恢复它们:如果您有一个复杂的继承层次结构,您不能将任何奇数指针强制转换为void*
,并希望能够将其恢复为原始类型!也就是说,为了方便地获取,例如,指向base
(来自下面的示例)的指针,并将其转换为void*
,您可以调用p->getThis()
,这比static\u cast(p)
容易得多,并且可以使用static\u cast(v)安全地将其转换为base*
:您可以反转隐式转换,但仅当您回溯到原始指针的确切类型时。也就是说,static\u cast(static\u cast(d))
其中d
是指向派生自base
类型的对象的指针是非法的,但是static\u cast(d->getThis())
是合法的
首先,为什么地址会改变?在示例中,base
是两个派生类的虚拟基类,但可能还有更多。其类实际上从base
继承的所有子对象将在另一个派生类的对象中共享一个公共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';
}
#包括
结构基
{
void const*getThis()const{返回此;}
};
结构派生1
:虚拟基地
{
INTA;
};
结构派生2
:虚拟基地
{
int b;
};
结构混凝土
:derived1
,被嘲笑
{
};
int main()
{
混凝土c;
derived2*d2=&c;
无效常数*dptr=d2;
void const*gptr=d2->getThis();
std::cout我在很多年前遇到过类似的东西。如果我没记错的话,当一个类操作同一个类的其他实例时需要它。一个例子可能是一个容器类,它可以包含自己的类型/(类?)。这可能是重写this关键字的一种方法。
假设您有一个内存池,在程序开始时完全初始化,例如,您知道在任何时候您最多可以处理50条消息CMessage。
创建一个大小为50*sizeof(CMessage)(这个类可能是什么)的池,CMessage实现getThis函数
通过这种方式,您只需覆盖“this”即可访问池,而不是覆盖新关键字。
这也可能意味着对象可能被定义在不同的内存空间上,比如说在SRAM上,在启动模式下,然后在SDRAM上
在这种情况下,同一个实例可能会返回不同的值,以便在重写时通过程序执行此操作。您的类可以有自定义的操作符&
(因此&a
可能不会返回的此)。这就是存在的原因。是否涉及模板?或继承?返回类型是否与包含函数的类的类型相同?因为如果不是这样的话,getThis
调用什么上下文就没有意义了?看起来它是用于强制转换到void*
。为什么它们不直接强制转换到void*
我不知道。Y你会在别人的代码中看到一些有趣的东西。@Dave是的,总是在别人的代码中,当然不会在我们的代码中我从来没有打开过一个月的代码文件。我的代码是摇滚的。+ 1只是为了<代码> GRP部分。老实说,在20年的C++中,我从来没有见过这种结构需要的情况,但也许那只是我……@ SyAM我想不出一个实例,但是我的SimalTalk经验有限。我想它变成了。一种语言中的事物,其原因可能是或可能不适用于C++。
有可能p0!=p1
!它所需要的只是bla
是一个指向一个适当构造类型的指针。@DietmarKühl指出。我仍然不知道它的实际用途。@Dave:正如Steve Clamage所说的那样