为什么允许将派生类的方法静态广播到基类的方法?

问题描述 投票:1回答:2

示例

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

c++ methods language-lawyer function-pointers static-cast
2个回答
4
投票

[是,static_cast允许以“不安全”的方式使用许多东西,例如将void*转换为另一种对象指针类型,将Base*转换为Derived*以及此。

尽管static_castreinterpret_castconst_cast相比可以认为是“相对安全”,但仍是强制转换。与所有强制类型转换一样,它表示忽略某些类型系统的安全要求的请求,然后程序员负责仔细,正确地使用它。


0
投票

输入

void f(B *b) {
  static_cast<D*>(b)->d_method();
  b->static_cast<void (B::*)()>(&D::d_method)();
}

您假设b在每种情况下都是D程度完全相同。当传递给需要基础成员指针的函数时,能够转换成员指针使caller可以从any派生类中提名任何函数。


-2
投票

您正在混合两种不相关的东西。大多数情况下,获取和使用指针是不相交的。是的,这很好[]

B1mp b1mp = static_cast<B1mp>(dmp); // hm, well that's weird 

这里没有违法行为。而且,如果您在适当的D对象上使用了它,一切都会好起来的。但是因为您违反了规则,并且将其用于实际上不是D的对象

B1 b1;
(b1.*b1mp)();

行为未定义。没什么新鲜的。 C ++标准并不要求诊断所有格式错误的构造。如果我们的程序包含这样的构造,这本质上就是我们的问题。

通过省略这种错误构造的要求,该标准为实现提供了极大的优化余地。只要代码中不包含任何“不良”内容,它就可以大大提高执行速度。例如,因为它不会因空指针或RTTI检查而陷入困境。

© www.soinside.com 2019 - 2024. All rights reserved.