Безопасно ли понижать объекты (не указатели) до их известного производного типа? - PullRequest
3 голосов
/ 14 февраля 2012

Будет ли опасность нарезки

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*/}

и obj1 и obj2 гарантированно будут Block объектами?

Я испытываю желание использовать:

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

но при прочтении краткого описания SO тега для нарезки объектов я испытываю желание использовать первый. Но я действительно не хочу никаких неприятных тихих нарезок.

Ответы [ 2 ]

7 голосов
/ 14 февраля 2012

Ссылки и указатели являются полиморфными.

Вы можете предпочесть

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

для даункаста, начинающегося со ссылки, эквивалентно *static_cast<const Block*>(&obj1).

1 голос
/ 14 февраля 2012

Прежде всего, не используйте броски в стиле C для снижения (или вообще никакого каста).Это очень опасно, потому что обходит все проверки компилятора.

Тем не менее, вам не нужно беспокоиться о нарезке, когда вы понижаете ссылки или указатели.

Для полиморфных объектов (т.е. объектов, которые имеютвиртуальные методы) вы можете использовать динамическое приведение, которое дает вам проверку времени компиляции + выполнения (возвращает ноль при понижении указателя на неправильный тип или выдает исключение bad_cast при понижении ссылки на неверный тип):

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

Для неполиморфных объектов вы можете использовать static_cast.

...