Объектно-ориентированное программирование на языке С++. Лясин Д.Н - 71 стр.

UptoLike

Составители: 

71
c.func2(5) дает результат 12 вместо ожидаемых 62, а вызов ptb->func1(2)
дает результат 4, а не 8. Дело в том, что в обоих случаях будет вызвана
функция func1 базового класса, а не переопределенная в производном
классе. Такое поведение объектов связано со статическим (ранним)
связыванием функций при трансляции программы. Когда транслятор в
процессе обработки программы встречает вызов какой-либо
функции, то
на место вызова он подставляет в текст оттранслированной программы
адрес вызываемой функции. Таким образом, компилируя тело компо-
нентной функции func2 класса Base, транслятор на место вызова функ-
ции func1 подставит адрес компонентной функции func1 из класса Base,
так как только эта функция с подобным именем ему известна (содер-
жимое класса
Child транслируется позже). В итоге функция Base::func2
всегда будет вызывать функцию Base::func1, как бы ни был оформлен
вызов самого метода func2.
Аналогично, компилируя тело функции main и встретив вызов ptb-
>func1(2), транслятор должен подставить на место вызова адрес функ-
ции, которой будет передано управление в данной точке программы. К
этому
моменту транслятору известны две функции с именем func1:
Base::func1 и Child::func1. Так как вызов метода осуществляется для ука-
зателя на объект Base, транслятор подставит на место вызова адрес
функции именно этого класса (определить, что в указатель ptb записан
адрес объекта класса Child, и поэтому вызвать метод Child::func1,
транслятор не
может).
Таким образом, можно сформулировать проблему: необходимо
обеспечить полиморфное поведение некоторой функции, определенной
в базовом классе и переопределенной в производных. Под полиморф-
ным поведением понимается реализация функции таким образом, чтобы
всякий раз при вызове функции вызывалась именно та ее реализация,
c.func2(5) дает результат 12 вместо ожидаемых 62, а вызов ptb->func1(2)
дает результат 4, а не 8. Дело в том, что в обоих случаях будет вызвана
функция func1 базового класса, а не переопределенная в производном
классе. Такое поведение объектов связано со статическим (ранним)
связыванием функций при трансляции программы. Когда транслятор в
процессе обработки программы встречает вызов какой-либо функции, то
на место вызова он подставляет в текст оттранслированной программы
адрес вызываемой функции. Таким образом, компилируя тело компо-
нентной функции func2 класса Base, транслятор на место вызова функ-
ции func1 подставит адрес компонентной функции func1 из класса Base,
так как только эта функция с подобным именем ему известна (содер-
жимое класса Child транслируется позже). В итоге функция Base::func2
всегда будет вызывать функцию Base::func1, как бы ни был оформлен
вызов самого метода func2.
     Аналогично, компилируя тело функции main и встретив вызов ptb-
>func1(2), транслятор должен подставить на место вызова адрес функ-
ции, которой будет передано управление в данной точке программы. К
этому моменту транслятору известны две функции с именем func1:
Base::func1 и Child::func1. Так как вызов метода осуществляется для ука-
зателя на объект Base, транслятор подставит на место вызова адрес
функции именно этого класса (определить, что в указатель ptb записан
адрес объекта класса Child, и поэтому вызвать метод Child::func1,
транслятор не может).
     Таким образом, можно сформулировать проблему: необходимо
обеспечить полиморфное поведение некоторой функции, определенной
в базовом классе и переопределенной в производных. Под полиморф-
ным поведением понимается реализация функции таким образом, чтобы
всякий раз при вызове функции вызывалась именно та ее реализация,

                                  71