Stroustrup omawia tę sprawę w sekcji 4.5 his 1989 multiple inheritance paper [PDF]:
Rozwiązanie jest opracowanie operacji konwersji (rzutowania) na test dla wartości wskaźnika 0 [...]
Dodatkowa złożoność i czas działania w czasie wykonywania to test i przyrost.
Implementacja sprawdza jawnie wartości puste i zapewnia, że wynik rzutowania nadal będzie wartością zerową. Było tak w C++ 98 i nie zmieniło się w C++ 11 i nullptr
.
Jest to szczególnie ważne w przypadku wielu klas bazowych, w których rzutowanie z klasy pochodnej na jedną z klas bazowych może wymagać zmiany rzeczywistej wartości wskaźnika.
W twoim przykładzie układ C
w pamięci zawiera najpierw bajty dla IA
, a następnie bajty dla IB
. Przesyłanie do IA
jest trival, jako wskaźnik do początku C
będzie również wskazywać na początek części IA
z C
. Przesyłanie do wersji IB
wymaga zmiany wskaźnika C
o rozmiar IA
. Wykonanie tej zmiany w przypadku nullptr doprowadziłoby do pojawienia się wskaźnika zerowego po rzutowaniu, stąd specjalne traktowanie wartości zerowych.
jako pointed out by aschepler, w odpowiedniej sekcji w standardzie to [conv.ptr] §4.10:
prvalue typu „wskaźnik do cvD
”, gdzie D
jest typu klasy może być skonwertowano do wartości prod. Typu "wskaźnik do cvB
", gdzie B
jest podstawową klasą [...] z dnia D
. [...] Wynik konwersji jest wskaźnikiem do podobiektu klasy podstawowej pochodnego obiektu klasy. Wartość wskaźnika pustego o wartości jest przekształcana na wartość wskaźnika pustego typu docelowego.
Generuje to '0 0' przy użyciu C++ 14: https: // ideone.com/iefRnb – EdChum
Przykład z wielokrotnym dziedziczeniem (a więc regulacją wskaźnika) byłby jeszcze bardziej interesujący. – Quentin
@Quentin Uzgodnione. Zaktualizuję pytanie. – Lingxi