Я проходил через «Множественное наследование для 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
может быть сделано без явного приведения. Это определенно означает, что кастинг обрабатывается неявно. Затем,
pc = pb
указатель, литье необходимо? РЕДАКТИРОВАТЬ
Джонатан Ми пометил этот вопрос как дубликатКакой тип броска идти от родителя к ребенку?«Я боюсь, я не согласен. Мой вопрос касается, почему кастинг и где это правило, которое направляет нас на кастинг или не на кастинг. Я думаю, что логика может быть такой же, но концепция совершенно другая. В своем вопросе он сомневается в (настаивает на том, чтобы не использовать динамическое приведение) использования dynamic_cast и static_cast. Мое сомнение еще несколько шагов позади его.
Это связано с типами, которые мы знать что объекты имеют. каждый C
также B
Таким образом, преобразование всегда работает (неявно).
каждый B
не является частью C
Таким образом, вы должны сообщить компилятору, что вы точно знаете, что это конкретное преобразование будет работать. Это использование явного приведения.
Правила допустимые неявные преобразования для неосновных типов следующие:
- Нулевые указатели могут быть преобразованы в указатели любого типа
- Указатели на любой тип могут быть преобразованы в указатели void.
- Повышение указателя: указатели на производный класс могут быть преобразованы в указатель на доступный и однозначный базовый класс без изменения его
const
или жеvolatile
квалификация.
Так когда приведение к базовому типу из C*
к B*
явное приведение не обязательно. Но потому что кастинг от B*
к C*
это указатель удрученный Можно использовать приведение в стиле C, но предпочтительным является одно из следующих:
dynamic_cast
может использоваться, учитывая, что выражение является B*
и new_type это C*
эта проверка во время выполнения будет выполнена, и понижение должно быть разрешено 1:
- Исследуется наиболее производный объект, указанный / идентифицированный выражением. Если в этом объекте выражение указывает / относится к общедоступной базе Derived, и если только один подобъект типа Derived получен из подобъекта, указанного / идентифицированного выражением, то результат точек приведения / ссылается на этот производный подобъект. (Это известно как «удрученный».)
- В противном случае, если выражение указывает / относится к общедоступной базе наиболее производного объекта, и, одновременно, наиболее производный объект имеет однозначный общедоступный базовый класс типа Derived, результат приведения точек / относится к этому производному (это известно как «sidecast».)
- В противном случае проверка во время выполнения завершится неудачно. Если 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
попытка приведет к неопределенному поведению.В вашем случае это довольно просто. Вы пытаетесь назначить указатель на объект класса B
на указатель, который указывает на объекты класса C
,
По сути, вы не можете сделать это, потому что объекты класса C
также обеспечить функциональность класса A
какие объекты класса B
не делайте. Таким образом, использование объекта класса B
где объект C
ожидается не определено, потому что B
не могу предоставить все C
есть.
Ну, компилятор знает, что указатель на C
можно ссылаться так же, как унаследованные class A
или же B
— так литьё вверх в A
или же B
может быть сделано неявно. Если пойти по другому пути, компилятор не знает, что указатель на объект C
, Это может быть другой класс, который также наследует A
, Добавляя актерский состав, вы по сути говорите:не беспокойтесь компилятор — я знаю, что это на самом деле класс типа C».