Ответ 1
Stroustrup обсуждает этот случай в разделе 4.5 свой 1989 многократный документ наследования [PDF]:
Решение заключается в разработке операции преобразования (литья) в тест для значения указателя 0 [...]
Добавленная сложность и накладные расходы во время выполнения - это тест и приращение.
Реализация проверяет явно для нулевых значений и гарантирует, что результат приведения остается нулевым значением. Это было верно в С++ 98 и не изменилось с С++ 11 и nullptr
.
Это особенно важно в случае нескольких базовых классов, где приведение из производного класса в один из базовых классов может потребовать изменения фактического значения указателя.
В вашем примере макет C
в памяти сначала будет содержать байты для IA
, а затем байты для IB
. Отбрасывание до IA
является треугольником, поскольку указатель на начало C
также укажет на начало IA
части C
. С другой стороны, для каста до IB
требуется сдвиг указателя C
на размер IA
. Выполнение этого сдвига в случае nullptr приведет к ненулевому указателю после актера, следовательно, специальная обработка для нулей.
В качестве отмеченного aschepler, соответствующий раздел стандарта [conv.ptr] §4.10:
Значение типа "указатель на cv
D
", гдеD
- тип класса, может быть преобразуется в prvalue типа "указатель на cvB
", гдеB
является базой класс [...] ofD
. [...] Результат преобразования - указатель на субобъект базового класса объекта производного класса. Нулевой указатель значение преобразуется в значение нулевого указателя для типа адресата.