Даже самые современные, глобально оптимизирующие компиляторы все еще придерживаются принципа «независимого перевода». Согласно этому принципу, каждая единица перевода составляется независимо, без каких-либо знаний о любых других единицах перевода, которые могут существовать во всей окончательной программе.
Когда вы объявляете класс с внешней связью, этот класс может использоваться в других единицах перевода. Компилятор не имеет представления о том, как ваш класс может использоваться в этих других единицах перевода. Таким образом, он должен предполагать, что для каждого экземпляра этого класса в общем случае требуется указатель виртуальной таблицы, правильно инициализированный в момент создания.
В вашем примере умный компилятор может выяснить, что динамический тип объекта *pFoo
равен FooDerived
. Это позволило бы компилятору оптимизировать код: генерировать прямой вызов функции FooDerived::bar
в ответ на выражение pFoo->bar()
(без использования виртуальной таблицы). Но тем не менее компилятору обычно все равно придется правильно инициализировать указатель виртуальной таблицы в каждом FooDerived
объекте.