8

我想将一个指向派生类成员的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 点)。

4

3 回答 3

8

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

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

如果您想开始看到这种失败,请混合virtual继承、多重继承(包括virtual和非)以及非平凡的多重实现继承。基本上当不同类型视图的地址this不同时,void从和返回到不同类型的转换是注定的。我在实践中看到了这种失败,事实上它可能会失败(由于代码库的更改远离转换点)这就是为什么你要小心始终使用完全相同类型的 void 指针进行转换.

于 2013-10-27T03:55:56.533 回答
3

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

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

现在,如果您void*在两者之间插入一个强制转换,编译器如何知道如何将其转换void*为适当的Base*地址?

如果您需要将 a 强制Derived*转换为 a void*,则应首先将其显式强制void*转换为原始Derived*类型。(从那里开始,从Derived*toBase*的转换无论如何都是隐式的,所以你最终会得到相同数量的转换,因此它实际上并不那么方便。)

于 2013-10-27T03:51:09.560 回答
0

从您自己提供的链接

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

这意味着只要您在执行之前知道向上转换是安全的,它就可以保证工作。这就是为什么你应该使用dynamic_castwhichnullptr如果不成功则返回。

如果有的话,可以这样想。

Type * t1;

static_castt1 到从它派生的类之一在编译时无法知道,除非对您的程序进行深入分析(显然它不是也不应该这样做),所以即使它最终是正确的,你也没有办法检查。dynamic_cast在运行时做额外的工作来检查转换是否成功,因此前缀是动态的。

于 2013-10-27T03:36:25.293 回答