Чтобы понять систему приведения, вам нужно погрузиться в объектную модель.
Классическим представлением простой иерархической модели является включение: если B
происходит от A
, то объект B
фактически будет содержать подобъект A
наряду со своими собственными атрибутами.
В этой модели понижение приведения представляет собой простую манипуляцию указателем со смещением, известным во время компиляции, которое зависит от схемы памяти B
.
Это то, что делает static_cast: статическое приведение называется статическим, потому что вычисление того, что необходимо для приведения, выполняется во время компиляции, будь то арифметика указателя или преобразования (*).
Однако, когда вступает в действие virtual
наследование, все становится немного сложнее. Основная проблема заключается в том, что при наследовании virtual
все подклассы совместно используют один и тот же экземпляр подобъекта. Для этого B
будет иметь указатель на A
вместо собственно A
, а объект базового класса A
будет создан за пределами B
.
Следовательно, во время компиляции невозможно вывести необходимую арифметику указателя: это зависит от типа объекта во время выполнения.
Всякий раз, когда есть зависимость от типа среды выполнения, вам нужна RTTI (информация о типе среды выполнения), а использование RTTI для приведения — это задача dynamic_cast.
В итоге:
- понижение времени компиляции:
static_cast
- пониженное время выполнения:
dynamic_cast
Два других также являются приведениями во время компиляции, но они настолько специфичны, что легко запомнить, для чего они нужны... и они вонючие, так что лучше их вообще не использовать.
(*) Как заметил @curiousguy в комментариях, это справедливо только для понижения. static_cast
позволяет повышать приведение независимо от виртуального или простого наследования, хотя в этом случае приведение также не требуется.
person
Matthieu M.
schedule
20.09.2010