Я не понимаю, почему указатели не являются полиморфными типами, поскольку мы можем использовать указатели базового класса, которые указывают на производные классы, для вызова виртуальной функции производного класса. Это говорит о том, что во время выполнения система может определить, является ли указатель полиморфным, не так ли?
(Это дополнительный вопрос от typeid для полиморфных типов)
Ваш вопрос страдает от неправильного использования терминологии. Язык C ++ проводит очень четкое различие между самими указателями и объектами, на которые указывают эти указатели. Типы указателей не являются полиморфными. В самом указателе нет ничего полиморфного. Что действительно может быть полиморфным, так это тип, на который указывает указатель. Когда указатель указывает на полиморфный тип, мы часто [неофициально] называем его полиморфный указатель (просто как сокращение для «указателя, который указывает на полиморфный тип»). Но когда дело доходит до таких вещей, как typeid
они видят вещи очень формально. За typeid
типы указателей никогда не бывают полиморфными.
И компилятор не определяет, является ли указатель полиморфным или нет во время выполнения. Это простое различие всегда сразу известно во время компиляции. Опять же, указатель называется полиморфный если он объявлен как указатель на полиморфный тип. Полиморфный тип тип класса, который содержит виртуальные функции (прямо или косвенно) Очевидно, что свойство быть полиморфным — это свойство типа во время компиляции.
Единственное, что определяется во время выполнения в таких случаях, это который конкретный тип указанного объекта в данный момент.
Фактически Стандарт (C ++ 11) использует термин полиморфный тип класса, скорее, чем полиморфный тип когда он описывает поведение typeid
:
Во-первых, здесь описывается, что происходит, когда typeid
применяется к lvalue типа class (т.е. когда он делает то, что вы ожидаете):
(§5.2.8 / 2) Когда
typeid
применяется к выражению glvalue, тип которого является полиморфным типом класса (10.3), результат относится кstd::type_info
объект, представляющий тип наиболее производного объекта (1.8) (то есть динамического типа), на который ссылается glvalue. […]
Но когда вы применяете его к указателю (т.е. не к lvalue типа class), применяется правило ниже:
(§5.2.8 / 3) Когда
typeid
применяется к выражению, отличному от glvalue типа полиморфного класса, результат относится кstd::type_info
объект, представляющий статический тип выражения. […]
Он говорит, что вы получаете статический (не динамический) тип, то есть вы получаете объявленный тип указателя, а не тип объекта, на который он фактически указывает.
Итак, да, у указателей есть полиморфные характеристики, как вы описываете, но не когда дело доходит до результата typeid
,
(На самом деле, все их полиморфные характеристики (включая, в частности, вызовы полиморфных функций-членов) проявляются только при явном разыменовании, используя *
или используя ->
, вовлечен. Таким образом, вы действительно должны сказать, что сами указатели не являются полиморфными; только объекты, которые вы получаете, когда разыменовываете их.)