![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Sherst |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 131 Регистрация: 26.10.2005 Репутация: нет Всего: 2 |
Привет всем!
Прочитал в одной книжке: "Для решения проблемы объектно-ориентированные языки используют концепцию позднего связывания. Когда вы посылаете объекту сообщение, код, который будет вызван, не определяется, пока не начнется время выполнения. Компилятор не убеждается, что функция существует, а выполняет проверку типа аргумента и возвращаемого значения, но он не знает точный код для выполнения." Это что получается я могу послать объекту сообщение(метод), который нигде не определен?
|
|||
|
||||
powerOn |
|
||||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
Нет. Тут немного другое имеется ввиду. Скажу сразу: позднее связывание это механизм вызова виртуального метода, заключается он в том, что адрес (а не имя ![]() Это имеет отношение только к виртуальным функциям, которыми в Java все и являются по умолчанию в отличии от С++. Не виртуальная функция в С++ вызывается по смещению относительно начала класса, а виртуальные как и в Java по указателю из таблицы виртуальных функций. Это все хорошо проявляется при наследовании классов и при переопределении методов. Вот пример
|
||||
|
|||||
Sherst |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 131 Регистрация: 26.10.2005 Репутация: нет Всего: 2 |
Т.е. выходит что на этапе выполнения программы (не компиляции) для класса создается
таблица виртуальных ф-ий ? А могу ли я как-то программно просмотреть содержимое таблицы виртуальных функций? И еще вопрос ![]() Заранее спасибо. |
|||
|
||||
powerOn |
|
||||||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
Существуют - static функции. Поменяй добавь этот идентификатор к функциям в примере и почувствуй разницу.
Нет на этапе компиляции. Все функции по умолчанию виртуальны, кроме статических.
Точно не знаю, посмотри в сторону Java Reflections, там есть возможность получить исчерпывающую информацию об объектах. |
||||||
|
|||||||
LSD |
|
||||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Нет, на этапе выполнения ![]() Пока класс не загружен в таблице его не будет, так что таблицы динамические.
Средствами Java никак, возможно в JNI есть методы, но сильно сомеваюсь. Т.к. эта штука очень сильно влияет на производительность и наверняка подвержена частым изменениям.
Наоборот, все не статические функции по умолчанию виртуальны, чтобы сделать их не виртуальными надо объявить их final. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
||||
|
|||||
powerOn |
|
||||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
Етественно пока класса в памяти нет, ни о какой таблице вирт.ф. говорить не стоит. Эта таблица появится только вместе с загруженным классом. Но размер таблицы виртуальных функций неизменен для определенного и зависит от количества виртуальных функции. Точнее размер вт = кол-ву виртуальных. функции. (Естественно с учетом наследования т.е. вирт. ф. предков тоже считаютя). И изменить его можно только добавив/удалив вирт.ф-цию. - Что во время выполнения невозможно. Я скорее воспринял этот вопрос как о размере таблицы, и скорее всего не много ни так.... ![]() Добавлено @ 21:42
функции final естественно не виртуальны, поскольку их нельзя переопределить. А виртуальность функции безсмысленна без переопределения. |
||||
|
|||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Тогда такой вопрос, каков размер таблицы виртуальных функций для java.lang.Object.toString()? ![]() Во время выполнения добавляется класс (загрузка то динамическая), а вот он уже может содержать новые виртуальные функции и их приходится добавлять в таблицу. На этапе компиляции известно только какие функции виртуальны а какие нет. В С++ все классы известны на этапе компиляции и поэтому можно сразу посчитать размер данной таблицы, но не в Java. Добавлено @ 21:50 Кстати не совсем, в Delphi можно объявить функцию с такой же сигнатурой что и в базовом классе, даже если та не является виртуальной. Это приведет к тому, что та функция будет скрыта в потомках, но виртуальной не будет (как именно она будет работать не скажу). Но возможность такая есть. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
LSD, извиняюсь, я немного запутался. Мы же загружаем скомпилированный байт код, и загрузчик прекрастно знает что за класс он грузит и от кого он наследован, и следовательно знает (или может просчитать) количество виртуальных функций для этого класса, создать для него таблицу вирт функции фиксированной длины. |
|||
|
||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
ОК, залезем немного во внутренности.
Возьмем все тот же java.lang.Object.toString(), когда ты пишешь в программе o.toString(), то в код вставляется вызов метода toString() из java.lang.Object. Потом во время исполнения происходит вызов этого метода причем в него передаются, помимо объявленных параметров еще и указатель на this и таблица виртуальных функций. Далее в этой таблице находится адрес функции которую надо вызвать для данного класса (если не найдем, то в C++ получим Pure Virtual Function Call, в Java IncompatibleClassChangeError). Ну а потом уже все просто метод мы знаем и вызываем его ![]() -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
Sherst |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 131 Регистрация: 26.10.2005 Репутация: нет Всего: 2 |
MoonCat привел пример в котором есть строка
Правильно ли я понимаю: Во время исполнения происходит вызов метода meth() по таблице виртуальных ф-ий класса B (из-за new B()), в который передается указатель this(он говорит о том что meth() был вызван для объекта a2). И почему тогда для static все наоборот? |
|||
|
||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Да. Смысл указателя this (в данном контексте), в том, чтобы определить истинный класс объекта для которого вызывается метод meth(), а затем уже по таблице виртуальных функций определить которую надо вызвать. А в static функциях, нет переменной this. Поэтому тип вызываемой функции определяется на этапе компиляции, и определяется он по имени класса. Даже если вызывать его не по имени класса, а через переменную:
Будет вызван статический метод из A. (кстати это плохой тон, так вызывать функции и компилятор выдает предупреждения). -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
Sherst |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 131 Регистрация: 26.10.2005 Репутация: нет Всего: 2 |
Теперь ясно.
Спасибо всем кто отозвался. |
|||
|
||||
Sherst |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 131 Регистрация: 26.10.2005 Репутация: нет Всего: 2 |
Забыл спросить
![]() Как компилятор по таблице виртуальных ф-ий находит именно нужный нам метод? |
|||
|
||||
chief39 |
|
|||
![]() карманная тигра ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1631 Регистрация: 20.5.2005 Где: Киев Репутация: 15 Всего: 77 |
Нууу... трудно сказать какой там код - в написании JVM ещё не участвовал ![]() А если серьёзно - то компилятор не ищет по сей таблице(она юзается во время выполнения - не компиляции). Он просто компилит, ничего не связывая. ТОЛЬКО если находит final - МОЖЕТ встроить жёстко тело метода вместо вызова его. А во время выполнения он берёт объект некий. Определяет его класс. например иерархия A->B->C. Создал C. Вызываешь метод f(). JVM смотрит есть ли у класса С метод f(). Есть? - отлично, выполним его! Нету - смотрим у B. Есть? - выполним! Нету? - ещё выше смотрим. Ну и не следует забывать о private и final. Если верхние методы будут private - то JVM вообще ничего не найдёт(вернее ты не сможешь вызывать такой метод ещё на этапе компиляции - верхние недоступны а нижестоящих - нету, иначе наверх бы не полезло). А если верхние будут final - то нижестоящие классы аналогичный метод не смогут поиметь ещё на этапе компиляции. То есть для всех наследников в роли такого метода будет вызываться именно этот родительский. А свой они создать не смогут - компилятор по жопе нашлёпает. ![]() ЗЫ: когда подгружается класс - в таблицу его методы заносятся. А когда я говорил "ищем" или JVM "смотрит"- это по той самой таблице ![]() ![]() ![]() Это сообщение отредактировал(а) chief39 - 22.3.2006, 11:06 -------------------- Люди - это свечи. Они либо горят, либо их - в жопу!(с) |
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
chief39, а как понять "смотрит", в том смысле как определяется что это имеено та функция что нам нужна, а ни какая нибудь другая? |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |