Когда и как решено использовать актерский состав или нет?

Я проходил через «Множественное наследование для C ++ Бьярна Страуструпа, опубликовано в майском выпуске журнала пользователей C / C ++ 1999 года«. Выдержка из того же (Страница 5/17),

4.4 Кастинг

Явное и неявное приведение может также включать изменение значения указателя с помощью дельты:

class A { void f(); };
class B { int f(); };
class C : A, B { };

C* pc;
B* pb;
pb = (B*)pc; // pb = (B*)((char*)pc+delta(B))
pb = pc; // pb = (B*)((char*)pc+delta(B))
pc = pb; // error: cast needed <-------------------- HERE
pc = (C*)pb; // pc = (C*)((char*)pb-delta(B))

Он показывает нам, что pb = pc может быть сделано без явного приведения. Это определенно означает, что кастинг обрабатывается неявно. Затем,

  1. почему, когда мы пытаемся pc = pb указатель, литье необходимо?
  2. Что и где это правило, которое направляет это?
  3. Это связано с увеличением / уменьшением указателя на дельта-значение?

РЕДАКТИРОВАТЬ

Джонатан Ми пометил этот вопрос как дубликатКакой тип броска идти от родителя к ребенку?«Я боюсь, я не согласен. Мой вопрос касается, почему кастинг и где это правило, которое направляет нас на кастинг или не на кастинг. Я думаю, что логика может быть такой же, но концепция совершенно другая. В своем вопросе он сомневается в (настаивает на том, чтобы не использовать динамическое приведение) использования dynamic_cast и static_cast. Мое сомнение еще несколько шагов позади его.

2

Решение

Это связано с типами, которые мы знать что объекты имеют. каждый C также BТаким образом, преобразование всегда работает (неявно).

каждый B не является частью CТаким образом, вы должны сообщить компилятору, что вы точно знаете, что это конкретное преобразование будет работать. Это использование явного приведения.

3

Другие решения

Правила допустимые неявные преобразования для неосновных типов следующие:

  • Нулевые указатели могут быть преобразованы в указатели любого типа
  • Указатели на любой тип могут быть преобразованы в указатели void.
  • Повышение указателя: указатели на производный класс могут быть преобразованы в указатель на доступный и однозначный базовый класс без изменения его const или же volatile квалификация.

Так когда приведение к базовому типу из C* к B* явное приведение не обязательно. Но потому что кастинг от B* к C* это указатель удрученный Можно использовать приведение в стиле C, но предпочтительным является одно из следующих:

  • dynamic_cast может использоваться, учитывая, что выражение является B* и new_type это C* эта проверка во время выполнения будет выполнена, и понижение должно быть разрешено 1:
  1. Исследуется наиболее производный объект, указанный / идентифицированный выражением. Если в этом объекте выражение указывает / относится к общедоступной базе Derived, и если только один подобъект типа Derived получен из подобъекта, указанного / идентифицированного выражением, то результат точек приведения / ссылается на этот производный подобъект. (Это известно как «удрученный».)
  2. В противном случае, если выражение указывает / относится к общедоступной базе наиболее производного объекта, и, одновременно, наиболее производный объект имеет однозначный общедоступный базовый класс типа Derived, результат приведения точек / относится к этому производному (это известно как «sidecast».)
  3. В противном случае проверка во время выполнения завершится неудачно. Если dynamic_cast используется в указателях, возвращается значение нулевого указателя типа new_type.
  • reinterpret_cast может быть использован, и всегда будет успешным. Но использование его результата определяется только если B это AliasedType и C DynamicType, одно из этих условий выполнено, 2й Пуля позволяет опускать:
  • AliasedType является (возможно, квалифицированным cv) DynamicType
  • AliasedType и DynamicType оба (возможно многоуровневые, возможно cv-квалифицированные на каждом уровне) указатели на один и тот же тип T
  • AliasedType является (возможно, cv-квалифицированным) подписанным или неподписанным вариантом DynamicType
  • AliasedType является агрегатным типом или типом объединения, который содержит один из вышеупомянутых типов в качестве элемента или нестатического члена (включая, рекурсивно, элементы субагрегатов и нестатические элементы данных содержащихся объединений): это делает его безопасным для получения пригодный для использования указатель на структуру или объединение, заданный указателем на его нестатический член или элемент.
  • AliasedType — это (возможно, cv-квалифицированный) базовый класс DynamicType
  • AliasedType is char или же unsigned char: это позволяет проверить представление объекта любого объекта в виде массива без знака.
  • static_cast может также использоваться, если и только если это известен что B* на самом деле полиморфно обращаясь к C объект. Если это не так, а static_cast попытка приведет к неопределенному поведению.
2

В вашем случае это довольно просто. Вы пытаетесь назначить указатель на объект класса B на указатель, который указывает на объекты класса C,

По сути, вы не можете сделать это, потому что объекты класса C также обеспечить функциональность класса Aкакие объекты класса B не делайте. Таким образом, использование объекта класса B где объект C ожидается не определено, потому что B не могу предоставить все C есть.

1

Ну, компилятор знает, что указатель на C можно ссылаться так же, как унаследованные class A или же B — так литьё вверх в A или же B может быть сделано неявно. Если пойти по другому пути, компилятор не знает, что указатель на объект C, Это может быть другой класс, который также наследует A, Добавляя актерский состав, вы по сути говорите:не беспокойтесь компилятор — я знаю, что это на самом деле класс типа C».

1
По вопросам рекламы [email protected]