【问题标题】:Why is this cross-cast not allowed?为什么不允许这种交叉投射?
【发布时间】:2023-03-31 00:54:01
【问题描述】:

考虑这个简单的例子:

struct Base1 {};

struct Base2 {};

struct Derived : public Base1, public Base2 {};

int main()
{
   Derived foo;
   Base1* foo1 = &foo;
   Base2* foo2 =  static_cast<Base2*>(foo1); 
}

我明白了:

Error: static_cast from 'Base1 *' to 'Base2 *', which are not related by inheritance, is not allowed

编译器应该有足够的信息来确定 Base2 可以在没有 RTTI (dynamic_cast) 的情况下从 Derived 到达并让我这样做:

Derived* foo3 = static_cast<Derived*>(foo1);
Base2* foo2 = foo3;

为什么不允许这样做? (有人可能会争辩说,编译器不知道foo1 是否属于Derived 类型,但static_cast 不会检查类型,即使从Base1 转换为Derived 时也是如此)

注意:这个question 和我的很相似,但不完全一样,因为这里我们是交叉转换基类,而不是派生类

【问题讨论】:

  • 恕我直言,从 Base1 转换为 Base2 完全不是一个好主意。你为什么要这样做?不要浪费时间。
  • 假设你是一个编译器,你将如何完成请求“将0x123456Base1 * 转换为Base2 *。生成的地址是什么,你是如何计算出来的?
  • 在另一个文件中你可能有struct Derived2 : public Base2, public Base1 {};,所以编译器不能单独基于Derived做任何假设。
  • Derived 内存布局是编译器已知的,因此它可以毫无问题地将Base1 转换为Base2。 (当然,假设Base1 实际上是Derived)。我认为约翰内斯所说的可能是它没有做出这种假设的真正原因。 (以及Base1Base2被视为不相关的原因)
  • 为什么假设 Base1 实际上是派生的?可能有各种其他类以 Base1 和 Base2 作为不同布局中的基础。

标签: c++ static-cast cross-cast


【解决方案1】:

static_cast 将失败,因为非正式地说,Base1Base2 不相关。

但是,如果您的类是多态dynamic_cast 将起作用:您可以通过添加虚拟析构函数来实现:

struct Base1 {virtual ~Base1() = default;};

struct Base2 {virtual ~Base2() = default;};

struct Derived : Base1, Base2 {};

int main()
{
   Derived foo;
   Base1* foo1 = &foo;
   Base2* foo2 =  dynamic_cast<Base2*>(foo1); 
}

在使用 composition(即接口)时,这种从 Base1Base2 的转换是惯用的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-02
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    相关资源
    最近更新 更多