[英]Why am I able to cast the this pointer of a base class to a pointer to a child class using the CRTP?
Consider the following classes, which employ the Curiously Recurring Template Pattern (CRTP): 请考虑以下类,这些类采用了好奇重复模板模式(CRTP):
template <typename T>
class Base
{
public:
virtual ~Base() {}
void typeOfThis()
{
cout << "Type of this: " << typeid(this).name() << '\n';
cout << "Type of *this: " << typeid(*this).name() << '\n';
}
void callFuncOfTemplateParam()
{
static_cast<T*>(this)->hello();
}
};
class Derived : public Base<Derived>
{
public:
void hello()
{
cout << "Hello from Derived!" << '\n';
}
};
When I execute the following: 当我执行以下命令时:
Base<Derived> * basePtrToDerived = new Derived();
basePtrToDerived->typeOfThis();
basePtrToDerived->callFuncOfTemplateParam();
I obtain these results, which make sense to me: 我获得了这些结果,这对我来说很有意义:
Type of this: P4BaseI7DerivedE
Type of *this: 7Derived
Hello from Derived!
Clearly, the call to hello
inside of callFuncOfTemplateParam
succeeds because the this
pointer points to an instance of Derived
, which is why I am able to cast the this
pointer from the type Base<Derived>*
to the type Derived*
. 显然,对
callFuncOfTemplateParam
内部的hello
调用成功,因为this
指针指向Derived
的实例,这就是为什么我能够将this
指针从Base<Derived>*
类型转换为Derived*
类型的原因。
Now, my confusion arises because when I execute the following: 现在,由于执行以下命令而引起混乱:
Base<Derived> * basePtrToBase = new Base<Derived>();
basePtrToBase->typeOfThis();
basePtrToBase->callFuncOfTemplateParam();
I obtain the following results: 我得到以下结果:
Type of this: P4BaseI7DerivedE
Type of *this: 4BaseI7DerivedE
Hello from Derived!
The types of this
and *this
make sense, but I don't understand how the call to hello
succeeds. this
和*this
的类型是合理的,但我不了解呼叫hello
如何成功的。 this
doesn't point to an instance of Derived
, so why am I able to cast the type of this
from Base<Derived>
to Derived
? this
并不指向的实例Derived
,所以为什么我能够施展的类型, this
从Base<Derived>
以Derived
?
Note that I also replaced the call to static_cast<T*>(this)->hello();
注意,我还替换了对
static_cast<T*>(this)->hello();
的调用static_cast<T*>(this)->hello();
with a call to dynamic_cast<T*>(this)->hello();
调用
dynamic_cast<T*>(this)->hello();
, and I still obtain the same results. ,但我仍然获得相同的结果。 I expected the
dynamic_cast
to return a nullptr
, but it doesn't. 我期望
dynamic_cast
返回nullptr
,但是没有。
I am very surprised by these results. 这些结果令我感到非常惊讶。 Thank you for any help clarifying my doubts!
感谢您为澄清我的疑问提供的帮助!
The cast used to call hello()
has undefined behavior when T
does not match the true type of the object that this
points to. 用于调用演员
hello()
已未定义行为的时候T
不符合真正的类型,对象的this
指向。 But hello()
isn't accessing anything via this
, so it doesn't really matter what this
actually points to. 但是,
hello()
不访问任何通过this
,所以它并没有真正的问题是什么this
实际上指向。 You could just as easily do reinterpret_cast<T*>(12345)->hello()
and it would still "work". 您可以轻松地执行
reinterpret_cast<T*>(12345)->hello()
,它仍然可以“正常工作”。 However you decide to cast this
wont make any difference since hello()
simply ignores the result (in the case of dynamic_cast
, see Does calling a method on a NULL pointer which doesn't access any data ever fail? ). 但是,您决定强制执行
this
不会有任何区别,因为hello()
只会忽略结果(对于dynamic_cast
,请参见在不访问任何数据的NULL指针上调用方法会失败吗? )。
Change your classes to introduce data members that hello()
tries to access via this
, and you will see very different results (ie, the code will likely crash, or report garbage, etc). 更改您的类以引入
hello()
试图通过this
访问的数据成员,您将看到非常不同的结果(即,代码可能会崩溃或报告垃圾等)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.