将对象(不是指针)向下转换为已知的派生类型是否安全?

时间:2012-02-14 19:27:41

标签: c++ downcast object-slicing

是否存在切片的危险

result Compare(const Osp::Base::Object &obj1, const Osp::Base::Object &obj2, int &cmp) const {
    cmp = ((const Block)obj1).NumSuperBlocks() - ((const Block)obj2).NumSuperBlocks();
}

其中

class Block : Object {/*Filler*/}

并确保obj1obj2Block个对象?

我很想使用:

    cmp = ((const Block*)&obj1)->NumSuperBlocks() - ((const Block*)&obj2)->NumSuperBlocks();

但在阅读SO的对象切片标签的简要描述时,我很想使用前者。但我真的不想要任何讨厌的无声切片。

2 个答案:

答案 0 :(得分:7)

引用和指针都是多态的。

您可能更喜欢

static_cast<const Block&>(obj1).NumSuperBlocks()

对于从引用开始的向下转换,它相当于*static_cast<const Block*>(&obj1)

答案 1 :(得分:1)

首先,不要使用C风格的演员阵容进行向下转换(或任何演员阵容)。这非常危险,因为它绕过了所有编译器检查。

也就是说,当你向下转换引用或指针时,你不必担心切片。

对于多态对象(即具有虚方法的对象),您可以使用动态强制转换,它为您提供编译时+运行时检查(向下转换指向错误类型的指针时返回null,或在向下转换引用时抛出bad_cast异常错误的类型):

Block & block = dynamic_cast<Block&>(obj);

对于非多态对象,您可以使用static_cast