static_cast从Derived *到void *到Base *

时间:2013-10-27 03:31:13

标签: c++ static-cast

我想将指向派生类成员的指针强制转换为void*,并从那里指向基类的指针,如下例所示:

#include <iostream>

class Base
{
    public:
       void function1(){std::cout<<"1"<<std::endl;}
       virtual void function2()=0;
};

class Derived : public Base
{
    public:
       virtual void function2(){std::cout<<"2"<<std::endl;}
};

int main()
{
    Derived d;
    void ptr* = static_cast<void*>(&d);
    Base* baseptr=static_cast<Base*>(ptr);
    baseptr->function1();
    baseptr->function2(); 
}

这会编译并提供所需的结果(分别打印12),但它是否可以保证有效?我在此处找到static_cast的说明:http://en.cppreference.com/w/cpp/language/static_cast 只提到转换为void*并返回指向相同类的指针(第10点)。

3 个答案:

答案 0 :(得分:8)

在一般情况下,通过静态转换将base转换为void到派生(反之亦然)是不安全的。

有些情况几乎可以肯定:如果所涉及的一切都是一个pod或标准布局,并且只涉及单一继承,那么事情应该没问题,至少在实践中是这样的:我没有章和节从标准来看,但一般的想法是,在这种情况下,基数保证是派生的前缀,并且它们将共享地址。

如果你想开始看到这个失败,请混合使用virtual继承,多重继承(virtual和非{)),以及多个非常重要的实现继承。基本上,当this的不同类型视图的地址不同时,从{返回到另一种类型的void转换是注定要失败的。我已经看到这在实践中失败了,事实上它可能会失败(由于代码库的变化远离了投射点),这就是为什么你要小心总是来往于void指针与完全相同的类型。

答案 1 :(得分:3)

一般来说,不,这不安全。

假设直接向Derived*转换Base*会导致不同的地址(例如,如果涉及多个继承或虚拟继承)。

现在,如果您在其间插入了一个演员,那么编译器如何知道如何将void*转换为适当的void*地址?

如果您需要将Base*投射到Derived*,则应首先将void*明确地转换回原始void*类型。 (从那里,从Derived*Derived*的演员阵容无论如何都是隐含的,所以你最终会得到相同数量的演员阵容,因此它实际上并没有那么方便。)

答案 2 :(得分:0)

从您自己提供的链接

  

9)指向某个类D成员的指针可以向上转换为指向其基类B成员的指针。此static_cast不进行检查以确保该成员实际存在于指向对象的运行时类型中。

意思是只要你知道在你做之前它是安全的,它可以保证工作。这就是为什么你应该使用dynamic_cast如果不成功则返回nullptr

如果你有这样的想法。

Type * t1;
如果没有对程序进行深入分析(显然它不是也不应该这样做),在编译时就无法知道t1的{p> static_cast到哪一个派生的类,所以即使它结束了正确你无法检查。 dynamic_cast在运行时进行额外的工作以检查转换是否成功,因此前缀是动态的。