如何从非多态虚拟基类向下转换? [英] How to downcast from non-polymorphic virtual base class?

查看:110
本文介绍了如何从非多态虚拟基类向下转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当没有涉及虚拟函数时,是否有从虚拟基类向下转换到派生类的方法?下面是一些代码来演示我在说什么:

Is there a way to downcast from a virtual base class to a derived class when there are no virtual functions involved? Here's some code to demonstrate what I'm talking about:

struct Base1
{
  int data;
};

struct Base2
{
  char odd_size[9];
};

struct ViBase
{
  double value;
};


struct MostDerived : Base1, Base2, virtual ViBase
{
  bool ok;
};


void foo(ViBase &v)
{
  MostDerived &md = somehow_cast<MostDerived&>(v);  //but HOW?
  md.ok = true;
}


int main()
{
  MostDerived md;
  foo(md);
}

请注意,代码仅供演示之用。我的实际场景是相当复杂的,并涉及模板参数和铸造从一个到另一个,只知道第一个是第二个的基地;它可以是正常或虚拟基础,并且它可以具有或可以不具有虚拟功能。 (请参见底部的简化示例)。我可以检测多态性案例和虚拟/非虚拟基本案例使用类型traits,并解决所有这些非多态虚拟基础。所以这就是我问的问题。

Please note that the code is for demonstration only. My real scenario is fairly complex and involves template parameters and casting from one to another, knowing only that the first one is a base of the second one; it can be a normal or virtual base and it may or may not have virtual functions. (See simplified example at the bottom). I can detect the polymorphic case and the virtual/non-virtual base case using type traits, and solve all of them except the non-polymorphic virtual base. So that's what I'm asking about.

我真的不能想办法做演员:

I can't really think of a way to do the cast:


  • 隐式转换即将到来;

  • Implicit conversions are right out; these only do upcasts.

static_cast 明确禁止从虚拟基类投射:

static_cast is explicitly forbidden for casting from a virtual base class:


5.2.9 / 2 ...和 B 既不是 D 的虚拟基类,也不是 D 的虚拟基类的基类。 ...

5.2.9/2 ... and B is neither a virtual base class of D nor a base class of a virtual base class of D. ...


  • dynamic_cast 因为下传需要多态类


    5.2.7 / 6 否则, / code>应是指向多态类型(10.3)的指针或glvalue。

    5.2.7/6 Otherwise, v shall be a pointer to or a glvalue of a polymorphic type (10.3).

    10.3 / 1 ...声明或继承虚拟函数的类称为多态类。

    10.3/1 ... A class that declares or inherits a virtual function is called a polymorphic class.


  • <$

  • reinterpret_cast doesn't apply here at all.

    如果<$ p>

    (注意所有引用都来自C ++ 11草案N3485)

    由于注意到上面的例子代码太多,下面是我的真实情况:

    In light of comments focusing on the above example code too much, here's a sketch of what my real situation is:

    template <class T_MostDerived>
    struct Bar
    {
      template <class T_Base>
      void foo(T_Base &b, typename std::enable_if<std::is_base_of<T_Base, T_MostDerived>::value>::type * = nullptr)
      {
        T_MostDerived &md = somehow_cast<T_MostDerived>(b);
        do_stuff_with(md);
      }
    };
    

    也就是说,我知道 T_Base 一个基类 T_MostDerived (我知道 T_MostDerived 实际上是最派生类型),但我不知道他们什么; Bar 是我的代码,是库的一部分,未知的客户端可以使用它。我可以检测它是一个非多态的虚拟基地,但我不能在这种情况下投射。

    That is, I know that T_Base is a base class of T_MostDerived (and I know that T_MostDerived is really the most derived type), but I don't know anything else about them; Bar is my code, part of a library, which unknown clients can use. I can detect that it's a non-polymorphic virtual base, but I can't cast it in such case.

    推荐答案

    MostDerived& 到其 ViBase& static_cast 可以明确表达这种转换,也可以做相反的转换。 static_cast 的转换类型。

    There is an implicit unambigious conversion from MostDerived& to its ViBase&. A static_cast can express such a conversion explicitly, and can also do the opposite conversion. That’s the kinds of conversions that static_cast does.

    下面的源代码说明了为什么:

    The source code below illustrates why:

    #include <iostream>
    using namespace std;
    
    struct B { virtual ~B(){} };
    struct D: virtual B {};
    struct E: virtual B {};
    struct X: D, E {};
    
    auto main() -> int
    {
        X   x;
        B&  b = static_cast<E&>( x );
    
        // Can't do the following for the address adjustment that would work for
        // D sub-object won't work for E sub-object, yet declarations of D and E
        // are identical -- so the address adjustment can't be inferred from that.
        //
        //static_cast<D&>( b );
    
        // This is OK:
        dynamic_cast<D&>( b );
    }
    

    基本上,如图所示,单独声明 D (或 E )。编译器也不能。这也排除了 reinterpret_cast

    Essentially, as this shows, you can't infer the address adjustment from the declaration of D (or E) alone. And neither can the compiler. This also rules out reinterpret_cast.

    这篇关于如何从非多态虚拟基类向下转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆