以下reinterpret_cast会导致未定义的行为吗?

时间:2017-06-02 23:06:10

标签: c++ pointers reinterpret-cast

以下代码中的rpd会导致未定义的行为吗?如果是这样,是否可以以类型安全的方式定义class Base { public: virtual ~Base() = default; }; class Derived : public Base { }; int main(void) { Derived d; Base* pb = &d; Base*& rpb = pb; Derived*& rpd = reinterpret_cast<Derived*&>(rpb); return 0; }

++

与我之前的recent question相关的排序。背后的背景;我正在尝试一个适配器类,它应该允许包含协变指针类型的向量本身用作协变类型。

1 个答案:

答案 0 :(得分:3)

强制转换本身没有UB(参见[expr.reinterpret.cast]),但通过重新解释的引用(rpb)访问引用的指针(rpd)会:

[basic.lval](标准草案)

  

如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义 56

     

56)此列表的目的是指定对象可能有或没有别名的情况。

     
      
  • (8.1)   对象的动态类型,
  •   

不适用,动态类型是Base*的静态类型,而不是glvalue类型的Derived*

  
      
  • (8.2)   对象的动态类型的cv限定版本,
  •   

没有cv资格,且类型仍然不匹配。

  
      
  • (8.3)   类似于对象的动态类型的类型
  •   

不适用。这是关于cv-qualifier de-composition,请参阅[conv.qual](对不起,段落中的许多下标很难输入html,并且是保持文本可读的必要条件。)

  
      
  • (8.4)   与对象的动态类型对应的有符号或无符号类型的类型
  •   

仅与整数类型相关。

  
      
  • (8.5)   与对象的动态类型的cv限定版本对应的有符号或无符号类型的类型,
  •   

同上。

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

Derived*既不是聚合也不是联盟。

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

Derived*不是Base*的基础。

  
      
  • (8.8)   char,unsigned char或std :: byte类型。
  •   

Derived*不是那些。

由于没有例外情况适用,因此Base*类型的glvalue访问Derived*的行为未定义。

  

我正在尝试一个适配器类,它应该允许包含协变指针类型的向量本身用作协变类型。

您的实验将无法维护基本的面向对象原则。

基本引用与派生协变,因为您无法通过基本引用对派生对象本身执行任何操作。

基类型的容器不能与派生容器协变,因为你可以使用一个容器(通过“引用”容器派生)基于你无法对派生容器做的事情做一些事情:添加对象其他派生类型。

虽然,如果容器是不可变的......它可能在概念上有效。实际上用C ++实现它是另一回事。