Указатель на подобъект базового класса. Какая версия виртуальной функции вызывается? - PullRequest
0 голосов
/ 27 января 2012

В dynamic binding вызов функции связан с реализацией функции в зависимости от типа объекта, на который указывает указатель.

Предположим, у нас есть следующий код:

base *bptr = new derived;
bptr->func();

Пусть функция func объявлена ​​виртуальной в базовом классе.Тогда версия виртуальной функции func производного класса будет вызываться во время выполнения из-за динамического связывания.

Я понимаю приведенную выше концепцию.

Но меня смутила следующая концепция, которую я изучил после изучения вышеуказанной концепции.

В приведенном фрагменте кода указательОбъект производного класса неявно преобразуется в указатель на объект базового класса.Тогда bptr будет фактически указывать на подобъект базового класса объекта производного класса, а не указывать на объект производного класса.

Поскольку указатель базового класса bptr указывает на подобъект базового классаво время выполнения не должна ли вызываться версия виртуальной функции базового класса func?

Ответы [ 3 ]

3 голосов
/ 27 января 2012

Кажется, вам не хватает того, что на самом деле означает динамическое связывание .Это означает, что даже если указатель (статически) ссылается на базовый субобъект, вызов будет передан (динамическому) типу завершенного объекта.

Общая реализация осуществляется с помощью таблицы виртуальных функций.Базовый подобъект будет хранить в качестве скрытого члена указатель на таблицу виртуальных функций фактического полного типа, к которому он принадлежит.Все вызовы виртуальных функций (для которых динамическая диспетчеризация не отключена) направляются через этот дополнительный уровень косвенности, гарантируя, что будут вызваны окончательные переопределения.

Что касается особенностей того, как эта таблица и скрытый указатель являютсяуправляемый компилятор создает электронные таблицы для каждого типа с виртуальными функциями и внедряет код в различные конструкторы для соответствующего обновления указателей.Таким образом, при создании базового подобъекта указатель ссылается на базовый vtable, но перед входом в производный конструктор введенный код обновит указатель (в базе) для ссылки на производный vtable.

1 голос
/ 27 января 2012

Не смущайтесь этим. «Указатель на объект производного класса неявно преобразуется в указатель на объект базового класса». Значение этого оператора состоит в том, что derived имеет некоторый метод derivedOnly(), которого нет в base. Теперь, если вы попробуете bptr->derivedOnly();, это выдаст ошибку, даже если вы действительно ссылаетесь на объект derived.

Итак, bptr действительно является указателем на base.

0 голосов
/ 27 января 2012

В этом примере:

base *bptr = new derived;
bptr->func();

класс base просто используется как-то как интерфейс, чтобы знать, какие методы могут быть вызваны, так как он указывает на экземпляр производного объекта. Vtable (http://en.wikipedia.org/wiki/Virtual_method_table) сделает так, чтобы был вызван метод из класса derived.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...