为什么向下转换在CRTP中定义了行为 [英] Why is the downcast in CRTP defined behaviour

查看:67
本文介绍了为什么向下转换在CRTP中定义了行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用CRTP模式已经有一段时间了,但是阅读有关向下转换的不确定行为的答案,我不明白为什么 static_cast< Derived&(this),其中的类型为 Base< Derived> * ,其定义为行为,其中 Derived 是从 Base< Derived> 公开继承的.

标准很明确:

static_cast<new_type>(表达式)

如果new_type是指向某个类D的指针或引用,而表达式的类型是指向其非虚拟基数B的指针或引用,则static_cast执行向下转换.如果B是模棱两可,不可访问或D的虚拟基础(或虚拟基础的基础),则这种下调是错误的.

但要查看类似的问题,请 C ++继承向下转换:

如何从点对象[基类]转换为子点对象[派生类]?

评分最高的答案:

您不能;除非点[ Base ]具有转换运算符,或者子点[ Derived ]具有转换构造函数,在这种情况下,对象类型无需转换即可进行转换."

另一个示例: static_cast父类到子类C ++

 //B:公共AA a;B * bptr = static_cast B *(& a); 

最受好评的评论:

这是未定义的行为."

但是然后说:

您可以使用CRTP或dynamic_cast安全地进行操作."

在这里( C ++ static_cast向下有效性)再次被提及:

 基本库{190};A&a = static_cast< A&>(基本); 

否[无效],Base类型的对象不是A [ Derived ]类型的对象"


在CRTP中进行的下调有何不同?为什么它不会导致不确定的行为,但是上述情况却会导致未定义的行为?按照上述答案的逻辑,是不是说类 Base< Derived> 不是类型为 Derived 的对象(相反,它是真的),但是您可以使用 static_cast ?

也许我只是误解了CRTP.

解决方案

重新访问第一段:

如果new_type是指向某个类D的指针或引用,而表达式的类型是指向其非虚拟基数B的指针或引用,则static_cast执行向下转换.如果B是模棱两可,不可访问或D的虚拟基础(或虚拟基础的基础),则这种下调是错误的.

,包括下一个句子:

此类static_cast不进行运行时检查以确保对象的运行时类型实际上为D,并且只有在通过其他方式(例如实现静态多态性)保证此前提条件的情况下,才可以安全地使用该对象.

CRTP使用/是静态多态性的另一个名称.

给出 struct D:B< D> ,如果 B< D> static_cast * this D& ,则这是定义的行为,因为 this 指针实际上是指向 D B< D>的指针..

I have used the CRTP pattern for a while, however reading answers about undefined behaviour related to downcasting I don't understand why the static_cast<Derived&>(this), where this is of type Base<Derived>* is defined behaviour, where Derived inherits publicly from Base<Derived>.

The standard is quite clear:

static_cast < new_type > ( expression )

If new_type is a pointer or reference to some class D and the type of expression is a pointer or reference to its non-virtual base B, static_cast performs a downcast. This downcast is ill-formed if B is ambiguous, inaccessible, or virtual base (or a base of a virtual base) of D.

But looking at similar questions, C++ inheritance downcasting:

How do I cast from a point object [Base class] to a subpoint object [Derived class]?

Top rated answer:

"You can't; unless either point [Base] has a conversion operator, or subpoint [Derived] has a conversion constructor, in which case the object types can be converted with no need for a cast."

Another example: static_cast parent class to child class C++

// B : public A
A a;
B* bptr = static_cast<B*>(&a);

Top rated comment:

"It's undefined behavior."

But then says:

"You can do it safely using either CRTP or dynamic_cast."

Here (C++ static_cast downcast validity) it is again mentioned:

Base base{190};
A& a = static_cast<A&>(base);

"No [it is not valid], an object of type Base is not an object of type A [Derived]"


How is the downcast performed in CRTP different; why does it not cause undefined behaviour but the cases above do? Following the logic of the answer above, is it not true to say that class Base<Derived> is not an object of type Derived (the converse it true), yet you can use static_cast?

Perhaps I'm simply misunderstanding CRTP.

解决方案

Revisiting the first paragraph:

If new_type is a pointer or reference to some class D and the type of expression is a pointer or reference to its non-virtual base B, static_cast performs a downcast. This downcast is ill-formed if B is ambiguous, inaccessible, or virtual base (or a base of a virtual base) of D.

and including the next sentence:

Such static_cast makes no runtime checks to ensure that the object's runtime type is actually D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism.

CRTP uses/is another name for static polymorphism.

Given struct D : B<D> if B<D> static_cast's *this to D&, then this is defined behaviour because the this pointer really is a pointer to both a D and a B<D>.

这篇关于为什么向下转换在CRTP中定义了行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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