示例
struct B1{int x; void f(){x = 1;}};
struct D : B1{int x; void f(){B1::x = 2;}};
using Dmp = void(D::*)();
using B1mp = void(B1::*)();
int main()
{
Dmp dmp = &D::f;
D d;
(d.*dmp)(); // ok
B1mp b1mp = static_cast<B1mp>(dmp); // hm, well that's weird
B1 b1;
(b1.*b1mp)();
dmp = &B1::f; // ok
}
并且此示例将编译并运行正常,并且不会出现问题。但是,等等,现在我要在D::x
中使用D::f
,而且现在-在运行时可能会发生任何事情。
是,您还可以static_cast
指向基数的指针到指向派生的指针。
static_cast<D*>( (B1*)0 )
但是在这里您可以使用RTTI来检查类型,或者在可能的情况下仅使用dynamic_cast
。
[是,static_cast
允许以“不安全”的方式使用许多东西,例如将void*
转换为另一种对象指针类型,将Base*
转换为Derived*
以及此。
尽管static_cast
与reinterpret_cast
和const_cast
相比可以认为是“相对安全”,但仍是强制转换。与所有强制类型转换一样,它表示忽略某些类型系统的安全要求的请求,然后程序员负责仔细,正确地使用它。
输入
void f(B *b) {
static_cast<D*>(b)->d_method();
b->static_cast<void (B::*)()>(&D::d_method)();
}
您假设b
在每种情况下都是D
程度完全相同。当传递给需要基础成员指针的函数时,能够转换成员指针使caller可以从any派生类中提名任何函数。
您正在混合两种不相关的东西。大多数情况下,获取和使用指针是不相交的。是的,这很好[]
B1mp b1mp = static_cast<B1mp>(dmp); // hm, well that's weird
这里没有违法行为。而且,如果您在适当的
D
对象上使用了它,一切都会好起来的。但是因为您违反了规则,并且将其用于实际上不是D
的对象
B1 b1; (b1.*b1mp)();
行为未定义。没什么新鲜的。 C ++标准并不要求诊断所有格式错误的构造。如果我们的程序包含这样的构造,这本质上就是我们的问题。
通过省略这种错误构造的要求,该标准为实现提供了极大的优化余地。只要代码中不包含任何“不良”内容,它就可以大大提高执行速度。例如,因为它不会因空指针或RTTI检查而陷入困境。