Здравствуйте! Сегодня мы продолжим разговаривать о том, как связаны конструкторы и виртуальные методы. Что будет, если мы из конструктора попытаемся вызвать виртуальный метод? Например, из конструктора класса "Animal" мы можем вызвать метод "Voice". И хороший вопрос, какой тип связывания будет выбран — позднее или ранее? На прошлом уроке мы говорили, что для виртуальных методов используются поздние связывания. Но также мы говорили, что каждый конструктор перед своим выполнением переключает VPointer на нужную таблицу виртуальных функций. Поэтому, на самом деле, компилятор может использовать и использует в телах конструкторов и деструкторов ранее связывание. Потому что это соответствует стандарту, а по производительности стоит намного дешевле. Поэтому, написав здесь вызов "Voice" в теле конструктора, мы можем быть уверены, что вызовется "Voice" из класса "Animal". Это хорошо. А сейчас давайте вспомним еще одно понятие желтого пояса — "абстрактный метод" и, соответственно, "абстрактный класс". Что это такое? Уберем пока экспериментальный выбор "Voice". И напомню, что, написав такое выражение, метод равен нулю, мы объявили метод "Voice" абстрактным. Соответственно, класс "Animal" стал абстрактным, и мы теперь не сможем его инстанцировать. При попытке сделать это, при попытке создать экземпляр класса "Animal", мы получим сообщение об ошибке. Мы увидели сообщение, что это абстрактный класс — у нас ничего не получится. Если абстрактный класс мы не можем создать, как же мы можем тогда вызвать абстрактную функцию? Есть ведь часто распространенная ошибка: "Вызов чисто виртуальной функции". Вы наверняка с ней сталкивались как пользователь. Как же она получается? Давайте попробуем ее вызвать. Для этого снова напишем тот самый вызов "Voice" из конструктора. И нам уже IDE сейчас подсказывает, что что-то пошло не так. У нас здесь warning соответствующий. Но, тем не менее, программа компилируется и запускается. Правда, после запуска она падает с ошибкой — с ошибкой ровно той, которая была рассмотрена на слайде: "Вызов чисто виртуальной функции". Почему это произошло? Ровно по той причине, которую мы рассмотрели в начале урока. Вызов "Voice", написанный в конструкторе "Animal", приводит к вызову метода "Voice" из класса "Animal". Вот к этому, который абстрактный. Это чисто виртуальная функция, у нее нет тела. И, конечно же, вызов ее приводит к ошибке. Итак, в завершении блока материала про таблицы виртуальных функций мы рассмотрели нюанс о том, как компилятор вставляет в тела конструкторов и деструкторов вызовы виртуальных методов, используя раннее связывание, просто потому что это дешевле. Также напоследок мы разобрали причины возникновения ошибки с вызовом чисто виртуальной функции. Спасибо вам за внимание!