Is it safe to downcast objects (not pointers) to their known derived type?
-
29-04-2021 - |
Question
Would there be a danger of 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();
}
Where
class Block : Object {/*Filler*/}
and obj1
and obj2
are assured to be Block
objects?
I'm tempted to use:
cmp = ((const Block*)&obj1)->NumSuperBlocks() - ((const Block*)&obj2)->NumSuperBlocks();
but on reading SO's brief description of the object-slicing tag I'm tempted to use the former. But I really don't want any nasty silent slicing.
Solution
References and pointers are both polymorphic.
You may prefer
static_cast<const Block&>(obj1).NumSuperBlocks()
for downcasting starting with a reference, it's equivalent to *static_cast<const Block*>(&obj1)
.
OTHER TIPS
First of all don't use C-style casts for downcasting (or any casting at all). It's very dangerous because it circumvents all compiler checking.
That said, you don't need to worry about slicing when you are downcasting references or pointers.
For polymorphic objects (i.e. objects that have virtual methods) you can use dynamic cast, which gives you compile-time + runtime checking (returns null when downcasting a pointer to the wrong type, or throws a bad_cast exception when downcasting a reference to the wrong type):
Block & block = dynamic_cast<Block&>(obj);
For non polymorphic objects you can use static_cast
.