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

Ton*_*vel 2 c++ pointers reinterpret-cast

下面的代码中的是否会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;
}
Run Code Online (Sandbox Code Playgroud)

有点与我之前最近的问题有关。这背后的背景;我正在试验一个适配器类,它应该允许包含协变指针类型的向量本身用作协变类型。

eer*_*ika 5

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

\n\n

[basic.lval](标准草案)

\n\n
\n

如果程序尝试通过非以下类型之一的泛左值访问对象的存储值,则行为未定义:56

\n\n

56) 此列表的目的是指定对象可以使用或不使用别名的情况。

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

不适用,动态类型是静态类型Base*,而不是Derived*泛左值的类型。

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

没有简历资格,并且类型仍然不匹配。

\n\n
\n
    \n
  • (8.3)\na类型类似于对象的动态类型,
  • \n
\n
\n\n

不适用。这是关于 cv 限定符分解,请参阅 [conv.qual](抱歉,段落中的许多下标在 html 中输入很麻烦,并且是保持文本可读的必要条件)。

\n\n
\n
    \n
  • (8.4)\na 类型是与对象的动态类型相对应的有符号或无符号类型,
  • \n
\n
\n\n

仅与整数类型相关。

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

同上。

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

Derived*既不是聚合也不是并集。

\n\n
\n
    \n
  • (8.7)\na 类型是对象动态类型的(可能是 cv 限定的)基类类型,
  • \n
\n
\n\n

Derived*不是 的基础Base*。

\n\n
\n
    \n
  • (8.8)\na char、unsigned char 或 std\xe2\x80\x8b::\xe2\x80\x8bbyte 类型。
  • \n
\n
\n\n

Derived*这些都不是。

\n\n
\n\n

Base*由于没有任何例外情况适用,因此通过类型的泛左值访问 a 的行为Derived*是未定义的。

\n\n
\n\n
\n

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

\n
\n\n

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

\n\n

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

\n\n

基本类型的容器不能与派生的容器协变,因为您可以使用基类的容器(通过“引用”容器派生的)基类容器执行某些操作,而您无法使用派生的容器执行此操作: 添加其他派生的对象类型。

\n\n

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

\n