在C ++中使用'static_cast'进行向下转换

时间:2011-06-12 16:02:20

标签: c++

考虑:

class base
{
    base();
    virtual void func();
}

class derived : public base
{
    derived();
    void func();
    void func_d();
    int a;
}


main
{
    base *b = new base();
    sizeof(*b); // Gives 4.
    derived * d = static_cast<derived*>(b);
    sizeof(*d); // Gives 8- means whole derived obj size..why?
    d->func_d();
}

在上面的代码中,我做了一个基指针的向下转换,它指向基对象到派生类指针。我想知道派生指针如何具有整个派生类对象。我可以调用派生类函数(仅在派生类中声明)。我没有在这里得到这个概念。

3 个答案:

答案 0 :(得分:20)

使用static_cast将对象强制转换为某种类型,但实际上并没有产生未定义的行为。 UB的症状差异很大。没有什么可以说UB不能允许成功调用派生成员函数(但是没有什么可以保证它会成功,所以不要指望它。)

以下是使用static_cast进行向下转换的规则,可在C ++标准的第5.2.9节([expr.static.cast])中找到(C ++ 0x措辞):

  

类型为“指向 cv1 B的指针”的prvalue,其中B是类类型,可以转换为类型为“指向的指针的prvalue” cv2 D“,其中D是从B派生的类,如果从”指向D的指针“转换为”指向{{的指针“的有效标准转换1}}“存在, cv2 cv1 B具有相同的cv资格,或更高的cv资格   既不是B的虚基类,也不是D的虚基类的基类。空指针值将转换为目标类型的空指针值。如果“指向 cv1 D的指针”的prvalue指向   到B实际上是B类型对象的子对象,结果指针指向封闭对象   类型为D。否则,演员表的结果是未定义的。

答案 1 :(得分:8)

执行运行时检查的唯一强制转换是dynamic_cast<>()。如果某个演员阵容在运行时无法运行,则应使用此演员表。

因此从leaf-&gt; root(向上转换)static_cast<>()进行投射可以正常工作 但是从root-&gt; leaf(向下转换)进行转换是危险的,并且(在我看来)应始终使用dynamic_cast<>()进行转换,因为它将依赖于运行时信息。成本很低,但总是值得为安全付出代价。

答案 2 :(得分:6)

编译时存在

sizeof。它既不知道也不关心在运行时,您的基础对象不指向derived。您试图用运行时变量影响编译时行为,这根本不可能。