Ben*_*igt 15 c++ polymorphism virtual dynamic-cast language-lawyer
这个问题的灵感来自于此处的评论.
请考虑以下代码段:
struct X {}; // no virtual members
struct Y : X {}; // may or may not have virtual members, doesn't matter
Y* func(X* x) { return dynamic_cast<Y*>(x); }
Run Code Online (Sandbox Code Playgroud)
有几个人建议他们的编译器会拒绝它的主体func.
但是,在我看来,这是否由标准定义取决于运行时的值x.从5.2.7([expr.dynamic.cast])部分:
表达式
dynamic_cast<T>(v)的结果是将表达式转换v为type 的结果T.T应该是对完整类类型的指针或引用,或者是"指向cv的 指针void".该dynamic_cast经营者不得抛弃常量性.如果
T是指针类型,则v应该是指向完成类类型的指针的prvalue,结果是类型的prvalueT.如果T是左值引用类型,则v应该是完整类类型的左值,结果是由引用的类型的左值T.如果T是右值引用类型,则v应该是具有完整类类型的表达式,并且结果是由引用的类型的xvalueT.如果类型
v是相同的T,或者T除了类对象类型inTcv-qualified比类对象类型更相同外,v结果是v(必要时转换).如果值
v是指针大小写中的空指针值,则结果是类型的空指针值T.如果T是"指针CV1
B"和v具有类型"指针CV2D",使得B是一个基类的D,其结果是一个指针,指向唯一B的的子对象D的对象指向的v.同样,如果T是'参照CV1B’并且v类型为cv2D,这B是一个基类D,结果是 引用B的D对象的唯一子对象v.结果是左值,如果T是左值引用,或者xvalue,如果T是右值引用.在指针和参考案例,如果cv2具有比cv1更大的cv资格或者如果B是不可访问或模糊的基类,则程序是不正确的D.否则,
v应该是指向多态类型的左值或左值.如果
T是"指向cv的 指针void",则结果是指向由其指向的最派生对象的指针v.否则,将应用运行时检查以查看指向或引用的对象是否v可以转换为指向或引用的类型T.)指向或引用的最派生对象v可以包含其他B对象作为基类,但是这些被忽略了.如果
C是T指向或引用的类类型,则运行时检查在逻辑上执行如下:
如果,在指向(引用)的最多派生对象中
v,v指向(引用)public对象的基类子C对象,并且只有一个对象类型C是从v结果点指向(引用)的子对象派生的(引用))到那个C对象.否则,如果
vpoint(引用)到public最派生对象的基类子对象,并且最派生对象的类型具有类型的基类C,那是明确的public,并且结果指向(引用)该C子对象的子对象.大多数派生对象.否则,运行时检查 失败.
失败的强制转换为指针类型的值是所需结果类型的空指针值.抛出失败的强制转换为引用类型
std::bad_cast.
我读这个的方式,多态类型的要求仅适用于上述条件都不满足的情况,其中一个条件取决于运行时值.
当然,在少数情况下,编译器可以肯定地确定输入不能正确地为NULL(例如,当它是this指针时),但我仍然认为编译器不能拒绝代码,除非它可以确定将到达语句(通常是一个运行时问题).
警告诊断在这里当然很有价值,但它是否符合标准,编译器会拒绝此代码并出现错误?
非常好的一点。
注意在C++03中5.2.7/3和5.2.7/4的写法如下
3如果v的类型与所需的结果类型相同(为方便起见,在本描述中将其称为R ),或者它与R相同,只是 R 中的类对象类型比R中的类对象类型更具 cv 限定性v中的类对象类型,结果为v(必要时进行转换)。
4如果v的值是指针情况下的空指针值,则结果是R类型的空指针值。
对 5.2.7/3 中引入的类型的引用R似乎暗示 5.2.7/4 旨在成为 5.2.7/3 的子条款。换句话说,5.2.7/4 似乎仅适用于 5.2.7/3 中描述的条件,即类型相同时。
然而,C++11中的措辞有所不同,不再涉及R,这不再表明 5.2.7/3 和 5.2.7/4 之间有任何特殊关系。不知道是不是故意改的……
| 归档时间: |
|
| 查看次数: |
329 次 |
| 最近记录: |