究竟什么是不安全的static_cast?

时间:2016-05-27 10:45:29

标签: c++ undefined-behavior static-cast

我写了一个不安全static_cast的小例子:

#include <iostream>

class A
{
public:
    virtual int getA(){ return 1; }
};

class B : public A
{
public:
    virtual int getA() { return 2; }
    int getB() { return 3; }
};

int main()
{
    A a;
    B b;
    B* b1 = static_cast<B*>(&a);

    std::cout << "b.getA(): " << b.getA() << std::endl;
    std::cout << "b.getB(): " << b.getB() << std::endl;
    std::cout << "b1->getA(): " << b1->getA() << std::endl;
    std::cout << "b1->getB(): " << b1->getB() << std::endl;
}

输出:

b.getA(): 2
b.getB(): 3
b1->getA(): 1
b1->getB(): 3

我认为它不安全,因为我在创建B时从未运行b1构造函数,尽管将其作为B对象访问。显然,输出的差异表明b1没有指向B对象,而是指向A对象,正如预期的那样。

这方面的其他方面是不安全的。它是否涉及未定义的行为甚至像这样执行static_cast?否则,访问getAgetB方法可能是未定义的行为吗?

还有别的吗? (我不关心在这个例子中我不关心的遗漏的虚拟析构函数)

cpp.sh上可用的代码:http://cpp.sh/7sxtz

2 个答案:

答案 0 :(得分:1)

执行print后访问*b1的值是未定义的行为:

  

static_cast   如果程序试图通过除了其中一个之外的glvalue访问对象的存储值   以下类型行为未定义

     

- 对象的动态类型,

     

- 对象的动态类型的cv限定版本,

     

- 与对象的动态类型相似的类型(如4.4中所定义)

     

- 与对象的动态类型对应的有符号或无符号类型

     

- 对应于动态类型的cv限定版本的有符号或无符号类型   对象,

     

- 聚合或联合类型,包括其元素中的上述类型之一或非   静态数据成员(包括递归地,子集合的元素或非静态数据成员)   或包含联盟),

     

- 一种类型,是对象动态类型的(可能是cv限定的)基类类型,

     

- char或unsigned char类型。

答案 1 :(得分:1)

static_cast<B *>(&a)导致未定义的行为。

C ++ 14 [expr.static.cast] / 11:

  

[...]如果类型为“指向cv1 B的指针”的prvalue指向实际上是B类型对象的子对象的D,则生成指针指向D类型的封闭对象。否则,行为未定义。