【问题标题】:dynamic_cast confusiondynamic_cast 混淆
【发布时间】:2011-05-11 08:22:31
【问题描述】:

我放弃了……

$5.2.7/2- "如果 T 是指针类型,v 应该是指向的指针的右值 完整的类类型,结果是 T 类型的右值。如果 T 是 引用类型,v 应该是一个左值 一个完整的类类型,并且 结果是类型的左值 由 T 引用。”

按照上面的,下面的代码应该是良构的。

struct A{};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

但事实并非如此。所有编译器都抱怨 dynamic_cast 的操作数不是多态的,符合

$5.2.7/6- 否则,v 应为 指向或左值的指针 多态类型(10.3)。

所以我的问题是 $5.2.7/2 是什么意思?为什么 $5.2.7/6 会出现在这里?

【问题讨论】:

    标签: c++ dynamic-cast


    【解决方案1】:

    嗯,5.2.7 中的所有要求都应该一起遵守。你不能在 5.2.7/2 之后停下来开始编写可以满足“直到 5.2.7/2”的所有内容的代码。整个5.2.7定义了dynamic_cast的规范。

    多态性需求被挑出来,因为它是有条件的。当您使用dynamic_cast 进行向上转换时,多态要求不适用(实际上,dynamic_cast 相当于向上转换中的static_cast)。仅当您将dynamic_cast 用于向下转换或交叉转换时,多态要求才适用。

    dynamic_cast 的规范是按顺序组织的,这意味着它首先处理更简单的情况,然后处理更复杂的应用程序。您应该逐步阅读它,直到它涵盖您的具体情况。您在该路径上阅读的所有内容都会累积应用,而“否则”的意思是:“如果我们尚未涵盖您的情况,请继续阅读”。

    【讨论】:

    • 嗯。好的。但是“否则”是什么意思呢?
    • 正是我的问题。在标准的许多其他部分中,“否则”的用户给出了一种“逐步”的算法程序。
    • 谢谢 AndreyT。我认为史蒂夫的表述方式令人信服。 “否则”适用于 5.2.7/5 而不是前面的所有条款。我希望这样的混淆能够达到标准委员会的潜在地址。
    • 这意味着没有对象切片就无法正确向上转换,那么dynamic_cast对向上转换没有用。
    【解决方案2】:

    为了在您的示例中执行 downcast,结构 A 需要是多态的,并且具有 RTTI。这是一个有效的调整版本:

    struct A{virtual void f(){}};
    struct B : A{};
    
    int main(){
       B b;
       A a, &ar1 = b;
    
       B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
       //B& rb2 = dynamic_cast<B&>(a);    // and also here?
    }
    

    通过添加一个 virtual 使其具有多态性,可以为该类启用 RTTI,从而允许向下转换。

    请注意,您的第二个示例无法运行 - 因为您将 pod (a) 投射到对 pod 的引用 - 这是不允许的。


    更新:

    您的代码在 5.2.7.5 下不允许使用,在 5.2.7.6 下也不允许使用。我的调整使它在 5.2.7.6 下工作

    【讨论】:

    • 谢谢亚历克斯。但这不是我的问题。
    【解决方案3】:

    “否则”在这种情况下是指“除非适用 5.2.7/5 中的条件”。

    您可以这样说,因为 /2 对程序提出了关于 dynamic_cast 操作数的要求(注意“v 应为左值”的“shall”语言与“the结果是一个左值”)。与标准中的其他地方一样,表达要求并不一定意味着它是唯一要求。其他条款可以说明额外的要求。在这种情况下,/6 声明了一个仅在某些情况下适用的额外要求,具体取决于 T 和 v 的静态类型。

    /3, /4, /5 告诉你结果的value,完全符合/2 中的要求。它们都没有以“否则”开头。所以对我来说,很明显它们不会形成从 /2 开始的“else if”链。

    一些括号或其他东西可能会更清楚地说明这一点(即 /6 中的“否则”适用于 /5 中的“if”,而不适用于 /2、/3 或 /4 中的“if”)。但这不是房子的风格。

    除此之外,/5 中的“否则”在逻辑上无法有意义地应用于/2 中的条件。 /1 表示 T 必须是“指向完整类类型的指针或引用,或 cv void*”。 /2 涵盖两种情况 - 指针类型和引用类型。这就是一切。 /2 没有“否则”(除非要说“否则,符合标准的编译器必须发出诊断”,但这是隐含的)

    【讨论】:

    • 是否还有其他情况,标准中的“否则”以可能不清楚的方式使用
    • 标准中使用的 b/w 'shall' 和 'will' 有什么区别?
    • 我不保证它是 100% 一致的,但“应该”用于强调某事是一种限制/要求(在程序上或在实施上,取决于上下文)。 “将”或“是”用于陈述您可以信赖的事情,而不是您实际做的事情。当然,大多数这些“是”的东西最终也会成为对某个地方的实现的要求,所以这主要是一个重点问题。
    • 这是我的另一个想法'如果 T 是指针类型,v 应该是指向完整类类型的指针的右值,结果是 T 类型的右值。由于这谈论'T =指针,v = Rvalue',我认为/ 6谈论'T =指针,v = lvalue'。我在这个想法中看到了一些优点
    • @Chubsdad:我明白你的意思,但文本是“如果 T 是指针类型,v 应该是右值”,而不是“如果 T 是指针, 并且 v 是一个右值”。除了指向完整类类型的右值指针之外,这没有给 v 留下任何空间。您阅读该标准的次数越多,您就越习惯于处理它的细微之处……但是,在这种情况下还有另一个细微之处,那就是左值转换为右值。所以实际上 v can 是一个 could 被视为左值的表达式,但 /2 表示它将被视为右值。限制是类型。
    猜你喜欢
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 2014-05-06
    • 2015-02-02
    • 2012-06-02
    • 2012-08-15
    • 2019-06-26
    • 2012-04-18
    相关资源
    最近更新 更多