我想将指向派生类成员的指针强制转换为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();
}
这会编译并提供所需的结果(分别打印1
和2
),但它是否可以保证有效?我在此处找到static_cast
的说明:http://en.cppreference.com/w/cpp/language/static_cast
只提到转换为void*
并返回指向相同类的指针(第10点)。
答案 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
在运行时进行额外的工作以检查转换是否成功,因此前缀是动态的。