Позвольте мне обобщить предыдущие ответы.
Здесь на самом деле есть две проблемы. Одним из них является нарезка. Вы инициализируете массив virs с копией subvir. В таких случаях компилятор вырезает часть vir из subvir и копирует ее в массив, так что вы действительно получаете только объекты vir. Теперь, в вашем конкретном случае, subvir не имеет дополнительных элементов данных, кроме элементов vir, поэтому срезы несколько вырождены, и объект vir очень похож на subvir. Однако vir и subvir - это разные классы, и объект в массиве оказывается объектом vir, а не объектом subvir, замаскированным под vir. Один из способов, с помощью которого различия между этими двумя фактами проявились бы практически, даже если бы оба имели одинаковые элементы данных, заключается в том, что в vir были виртуальные функции, перегруженные subvir. В этом случае указатель vtable в объекте в массиве будет указывать на vtable vir, а не subvir. Конечно, было бы еще более явно, если бы subvir содержал дополнительные элементы данных, которых нет в vir.
Второй вопрос - полиморфизм. В момент использования (вызов move ()) компилятор думает, что вы вызываете метод move () объекта типа vir (так как массив является массивом virs). (Компилятор, конечно, правильно думает, так как из-за среза, вырожденного, каким он может быть в этом случае.) Если бы это был фактически объект subvir, как вы и предполагали, вы могли бы вызвать subvir :: move (), вызвав move ( ) виртуальный в вир.
Чтобы получить желаемое поведение, вы можете использовать массив указателей (но тогда вы будете работать непосредственно с sv1, а не с его копией, если вы сначала не создали копию и не инициализировали массив указателем на копию).