【问题标题】:reinterpret_cast, casting to brother classreinterpret_cast,转换为兄弟类
【发布时间】:2012-08-15 19:02:59
【问题描述】:

我只是想知道以下 C++ 代码是否可以保证工作:

struct B1 {
    virtual void f() {};
};

struct B2 {
    virtual void f2() {};
};

struct D:public B1,public B2 {
};

int main() {
    D d;
    B1 *b1=&d;
    if (dynamic_cast<B2*>(b1)) {
      B2* b2 = reinterpret_cast<B2*>(b1); //is this conversion valid?
    };
    return 1;
};

当然,你会为什么我需要这个? 因为我想替换这个:

C::C(B1* b): member(dynamic_cast<B2*>(b)?dynamic_cast<B2*>(b)->m():b) {};

具有更好的构造(通过性能,不检查类型安全两次):

C::C(B1* b): member(dynamic_cast<B2*>(b)?reinterpret_cast<B2*>(b)->m():b) {};

提前致谢!

【问题讨论】:

  • “因为我想用更好的东西(...)替换这个(...)”?你的前提是错误的。
  • 第二个比第一个好在哪方面?请不要说性能。我不是真正的“反过早优化”的人之一,但你不会为dynamic_cast 的性能而哀悼,无论如何使用虚拟方法之类的东西,它们或多或少都带来了相同的结果(可以忽略不计)性能开销(通常是比dynamic_casts, aynway 更好的方法)。
  • @ChristianRau - static_cast 在这里不起作用。 static_cast 可用于在转换时编译器知道的层次结构中向上或向下移动。它不会像这里讨论的那样进行交叉演员。
  • @ChristianRau - “内部”层次结构与“向上或向下”不同。静态施法只能向上或向下移动,而不是侧向移动。所以它可以从基类到派生类,或从派生类到基类,但不能从B1*B2*。这需要在运行时确定B1* 指向的对象的实际类型是派生类型,该派生类型也派生自B2

标签: c++ reinterpret-cast


【解决方案1】:

软件问题的解决方案通常是添加一个间接级别,在这种情况下是一个函数。假设 dynamic_cast 应该是 B2*(不是 B1),编写一个函数来做正确的事:

B1 *get_b(B1 *b) {
    B2 *b2 = dynamic_cast<B2*>(b);
    if (b2)
        return b2->m();
    else
        return b;
}

然后在初始化列表中使用该函数:

C::C(B1 *b) : member(get_b(b)) { }

【讨论】:

  • 这不是直接的答案,而是更好的方法。谢谢。
  • @gena2x - 有时正确的答案是不问问题。
  • 不确定我是否可以按照这种方式进行,因为这需要添加某种库来放置此功能,但不知何故我还是没想到 =)
  • @gena2x - 您可以将其设为内联函数,在与使用它的类相同的标头中定义。它可以(也可能应该)是该类的静态成员函数。
  • 这个“技巧”应该在许多类中多次使用,所以很遗憾,在本地翻译单元中添加一些内容无济于事
【解决方案2】:

不,这绝对是无效的。使用 reinterpret_cast 您可以安全地做的就是将其转换回原始类型;其他任何东西都是实现定义的。

【讨论】:

  • 谢谢,这回答了我的问题。
猜你喜欢
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多