big*_*iao 3 c++ static-cast language-lawyer
这里是stackoverflow 上对四种显式强制转换的讨论。但我在得票最多的答案中遇到了一个问题。
引用来自得票最多的 wiki 答案:
static_cast也可以通过继承层次结构进行转换。当向上转换(朝向基类)时,它是不必要的,但是当向下转换时,只要它不通过virtual继承进行转换,就可以使用它。但是,它不进行检查,并且将层次结构下降到实际上不是对象类型的类型是未定义的行为static_cast。
但在cppref中,我读到了一些不那么严重的内容:
static_cast < new_type > ( expression )
如果 new_type 是某个类 D 的指针或引用,并且表达式的类型是对其非虚拟基 B 的指针或引用,则
static_cast执行向下转型。如果 B 是不明确的、不可访问的或 D 的虚拟基(或虚拟基的基),则这种static_cast向下转型是错误的。这样不会进行运行时检查来确保对象的运行时类型实际上是 D,并且只能安全地使用如果这个前提可以通过其他方式来保证。
因此,在 cppref 中,它并没有说未定义的行为,而是说不那么严重,因为不安全。
所以当我做类似的事情时:
class A{virtual foo(){}};
class B:public A{};
class C:public B{};
int main()
{
C*pc=new C;
A*pa=static_cast<A*>(pc);//Ok,upcast.
B*pb=static_cast<B*>(pa);//downcast,**is it undefined or just not safe?**
C* pc1=static_cast<C*>(pb);//downcast back to C;
}
Run Code Online (Sandbox Code Playgroud)
还有一个问题,如果不是UB,解引用也是UB吗pb?
cppreference 用英文编写,旨在传达良好的理解,它实际上不是规范。但我对这里的措辞没有问题:
\n\n\n\n\n这样
\nstatic_cast不会进行运行时检查来确保对象的运行时类型实际上是 D,并且只有在通过其他方式保证此前提条件时才可以安全使用。
如果你保证了前提,那就没问题了。如果您不能保证前提条件,那么您的代码就不安全。代码不安全意味着什么?其行为未定义。
\n\n实际规范使用这样的措辞:
\n\n\n\n\n如果 \xe2\x80\x9c 类型的纯右值指向cv 1
\nB\xe2\x80\x9d 指向的 aB实际上是 类型对象的子对象D,则生成的指针指向类型的封闭对象D。否则,行为是未定义的。
无论哪种方式,在您的示例中,您的所有转换都是有效的。
\n\nB*pb=static_cast<B*>(pa);//downcast,**is it undefined or just not safe?**\nRun Code Online (Sandbox Code Playgroud)\n\n你缺少这个条件。沮丧本身并不是未定义的行为。如果那里实际上不存在派生类型的对象,则这只是未定义的行为。在本例中pa, 指向 a C,它是 a B,因此对 a 的强制转换B是安全的。
然而,这不是:
\n\nstruct B { };\nstruct D1 : B { };\nstruct D2 : B { };\n\nB* p = new D1;\nstatic_cast<D2*>(p); // undefined behavior, no D2 object here\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1272 次 |
| 最近记录: |