2010-03-10 2 views
4

Одним из определения привязки является то, что он является заменой имен функций адресами памяти.Почему виртуальные методы считаются ранними?

a) Таким образом, я предполагаю, что функции раннего связывания заменяются вызовами функций во время процесса компиляции, а при позднем связывании эта замена происходит во время выполнения?

b) Почему виртуальные методы также считаются ранними (таким образом, метод-метод найден во время компиляции, и создается код, который будет вызывать этот метод)? Насколько я знаю, с помощью виртуальных методов вызов фактического метода разрешается только во время выполнения, а не во время компиляции ?!

Thanx


EDIT:

1)

A a=new A(); 
a.M(); 

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

2)

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

Но если предположить, объект типа T создается с помощью отражения (при этом приложение даже не знает о существовании типа T), то как можно во время компиляции существует точка входа для данного типа объекта?

+0

Я не уверен, что C# является правильным тегом для этого, так как C# не делает привязки, пока не будет загружено время загрузки. – Joshua

ответ

1

Виртуальные методы ранние, когда компилятор знает точный тип во время компиляции.

Если у компилятора нет точного типа, он вместо этого будет создавать привязку стиля поиска в формате vtable.

6

Late Binding

С поздним связыванием все у вас есть имя метода. Во время компиляции вы не знаете, существует ли метод. Это называется «утиная печать» на таких языках, как Ruby или Python.

Позднее привязка медленная, потому что вам нужно искать функцию по имени. Это также опасно, потому что вы не защищены от незначительных орфографических ошибок.

До версии 4 C# не поддерживает позднюю привязку, кроме явного вызова API отражения.

Раннее связывание

При использовании раннего связывания компиляции против фактического метода. Этот метод может быть отнесен непосредственно или может быть слотом в V-таблице. В любом случае вы не обязаны отказываться от исключения MissingMethod.

История

Visual Basic был хорошо известен для поддержки раннего и позднего связывания, но из-за него другие его ограничения он никогда не считался истинным динамическим языком. В то же время версии до 7 (a.k.a. VB.NET) имели очень плохую поддержку для принудительного раннего связывания, что затрудняло называть его статическим языком.

С .NET 4 можно сказать, что как C#, так и VB предлагают большинство функций, ожидаемых как от статических, так и от динамически типизированных языков.

В какой-то момент Java ошибочно сказал, что имеет позднюю привязку поддержки, когда это факт, что она имела только ранние ограничения, V-таблицы стиля ООП. На протяжении многих лет это приводило к путанице.

+0

Привет, я отредактировал свой начальный пост ... в случае, если вы найдете время – AspOnMyNet

1

Вызов виртуального метода может быть ранним, так как объясняет Джошуа (т. Е. Компилятор может видеть точный тип объекта, не происходит никакого полиморфизма), или это может быть сделано через v-таблицу.

C# только поздняя привязка при использовании отражения (и в следующей версии есть новое «динамическое» ключевое слово для запроса позднего связывания).

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

EDIT для решения новых вопросов:

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

Для (2) имеются две возможности. Во-первых, вызов функции выполняется через отражение через MethodInfo или такой. Это действительно поздно. Во-вторых, вызов функции выполняется через интерфейс или базовый класс, которые вызывающий абонент знает во время компиляции, хотя общий тип объекта неизвестен. В этом случае используется вызов v-table, поскольку макет v-таблицы определяется базовым классом или интерфейсом, поэтому вызывающий абонент знает об этом и может предопределять смещение в v-таблице.

+0

Привет, я отредактировал свой начальный пост ... в случае, если вы найдете время – AspOnMyNet

+0

Соглашение об именовании курионов. vtable lookup - единственная форма позднего связывания в C++. – Joshua

+0

указатели на функции находятся только в конце v-таблиц, и ни один из них не близок к тому, чтобы быть еще динамическим связыванием (которое, по общему признанию, не является частью стандартизованного языка C++, но тем не менее поддерживается большим количеством инструментов C++) –

Смежные вопросы