Докато указателят към базов тип действително сочи към екземпляр на производен тип, тогава такова използване не е недефинирано според стандарта C++. Въпреки това във вашия примерен код указателят b
не сочи към екземпляр на B
или някой от неговите производни типове (които няма), той сочи към екземпляр от A
. Така че вашият код всъщност извиква недефинирано поведение.
Намерих отговор на S.O, който казва, че може да доведе до UB, като го тествах, той се компилира и работи правилно.
Фактът, че някои кодове се компилират и работят правилно, не изключва възможността кодът да извиква недефинирано поведение, тъй като недефинираното поведение включва „изглежда, че работи“. Причината, поради която трябва да избягвате недефинирано поведение, е, че няма гаранция, че то ще работи по същия начин следващия път, когато извикате UB.
Това недефинирано поведение ли е? Ако е, какъв би бил правилният подход към този проблем?
Във вашата извадка, да, това е недефинирано поведение. Правилният подход ще зависи от това какво всъщност трябва да прави вашият код, тъй като примерът, който предоставяте, е в най-добрия случай академичен пример.
За да стане ясно, следната модификация на вашата функция main()
има добре дефинирано поведение и е изрично разрешена от стандарта C++:
B objectB;
A* ptrA = &objectB;
B* b = static_cast<B*>(ptrA);
b->Show();
Тук той е добре дефиниран, защото указателят ptrA
всъщност сочи към екземпляр на B
, въпреки че самият указател има тип A*
. В горния пример преобразуването от A*
към B*
и след това извикването на една от функциите на B
върху преобразувания указател ще работи. Разликата е, че в примера във вашия въпрос b
всъщност не сочи към екземпляр на B
.
Съответната клауза (акцентът е мой):
C++ стандарт 5.2.9/8 Статично предаване [expr.static.cast]
Rvalue от тип „указател към cv1 B
“, където B
е тип клас, може да се преобразува в rvalue от тип „указател към cv2 D
“, където D
е клас, извлечен (клауза 10) от B
, ако съществува валидно стандартно преобразуване от „указател към D
“ в „указател към B
“ (4.10), cv2 е същото cv-квалификация като или по-голяма cv-квалификация от cv1 и B
не е виртуален базов клас на D
. Стойността на нулевия указател (4.10) се преобразува в стойността на нулевия указател на типа дестинация. Ако rvalue от тип „указател към cv1 B
“ сочи към B
, който всъщност е подобект на обект от тип D
, полученият указател сочи към обхващащия обект от тип D
. В противен случай резултатът от кастинга е недефиниран.
person
In silico
schedule
16.02.2013