【问题标题】:C++ static_cast downcast validity [duplicate]C ++ static_cast向下转换有效性[重复]
【发布时间】:2017-11-15 15:02:53
【问题描述】:

static_cast 向下转换有效吗?

// non-virtual, may be non-trivially copyable
struct Base{
    int m_object;
};

// Derived class have only non-virtual functions
struct A : Base{
    void arggh(){
        std::cout << "Arrghh " << m_object;
    }
};

int main() {
    Base base{190};
    A& a = static_cast<A&>(base);
    a.arggh();
    return 0;
}

我的意思是,创建基类,然后转换为派生类。

Live

【问题讨论】:

  • 不,Base 类型的对象不是A 类型的对象
  • 只是好奇,你为什么要这样做?
  • 你应该做反转 Base* b = new A();并且您拥有的所有常用方法都应该是“虚拟的”。这就是你处理它的方式,这就是有一个指定合同的接口的原因。
  • @miradham Wel...... 我发现自己处于开始编写代理对象的情况,我可以轻松地重新创建它(它只有 1 个 ptr)。然后我需要 Proxy + 一些数据......然后我想这真是太糟糕了...... :) 很难用两个词来解释。
  • @appleapple 不完全是 - 这是非虚拟类。

标签: c++


【解决方案1】:

static_cast 用于执行向下转换不执行任何安全检查。由于Base&amp; 有可能引用A 的实例,因此转换继续进行,并且由于它实际上引用了A,我们进入未定义的行为领域*支持>.

另一方面,dynamic_cast 更安全。它将执行检查并在引用转换的情况下抛出异常,或在指针转换的情况下返回nullptr

但是,由于您的基类缺少任何虚函数,dynamic_cast 是不可能的,因此您需要至少使用一个虚析构函数对其进行修改:

class Base{
public:
    int m_object;
    virtual ~Base()=default;
};

现在如果我们尝试投射:

A* a = dynamic_cast<A*>(&base);
if (a)
    a->arggh();
else
    std::cout << "null\n";

我们的输出是


*相关标准见[expr.static.cast]:

[对于像static_cast&lt;D&amp;&gt;(b) 这样的转换,其中bD 的基类的一个实例],如果类型为“cv1 B”的对象实际上是一个基类D 类型对象的类子对象,结果引用 D 类型的封闭对象。否则,行为未定义。

[expr.dynamic.cast] 中的相关标准语

转换为指针类型失败的值是所需结果类型的空指针值。对引用类型的强制转换失败会引发与类型处理程序匹配的类型异常 std::bad_cast

【讨论】:

  • 请注意,添加虚拟成员函数并执行 dynamic_cast 有性能成本。
【解决方案2】:

没有。

并非所有Base 对象都是A1 类型,尽管反过来也是如此,static_cast 将在那个方向上工作。 p>


1另一个翻译单元可能有一个继承自 Base 的类。

【讨论】:

  • 但派生类“空”,大小为零,非虚拟coliru.stacked-crooked.com/a/ea14a7cd238064e1
  • @tower120:那是 UB。
  • @tower120 恭喜你,你遇到了最糟糕的 UB:“但它现在在这个程序调用的机器上工作!”一。
  • @Revolver_Ocelot 我实际上认为它现在可以在任何地方工作(它的偏移量为零)......但是 UB 是 UB。
【解决方案3】:

一点也不。

假设Base在内存中由这个块[--]表示,A是[--+],在这里你可以看到A包含一个部分Base(带有小'-')。

当你创建一个 Base 时,你有你的 [--] 然后你将它转换为 A 这意味着你说它实际上是 [--+] 但是 [--] 之后的内存不对应[--+]

正如你对这个例子的理解,你可以将 A 转换为 Base,因为 [--+] 包含 [--]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2021-11-10
    相关资源
    最近更新 更多