Как компилятор C++ знает который реализация виртуальной функции звонить?

Вы можете использовать метод format для замены заполнителей фактическими значениями. Вот самый простой пример:

template = "Hello, %{name}!"
format(template, name: "World")
=> "Hello, World!"

И ваш код может выглядеть так:

# query.sql
SELECT DISTINCT field1, field2, field3
FROM db
WHERE field1 = '%{value}'

# ruby file
def query_example(value)
  query = File.read("query.sql")
  results = @client.execute(format(query, value: value))
end
9
задан Jeremy Ruten 14 October 2008 в 22:43
поделиться

6 ответов

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

vtbl содержит набор указателей, один для каждой виртуальной функции. Таким образом во времени выполнения, код просто использует объект vptr располагаться vtbl, и оттуда адрес фактической переопределенной функции.

В Вашем конкретном случае, Polygon, Rectangle, и Triangle у каждого есть a vtbl, каждый с одной записью, указывающей на его соответствующее area метод. Ваш ppoly1 будет иметь a vptr указывая Rectangle vtbl, и ppoly2 так же с Triangle vtbl.Надеюсь, это поможет!

24
ответ дан 4 December 2019 в 06:35
поделиться

Chris Jester-Young дает основной ответ на этот вопрос.

Википедия имеет больше подробно обработка.

Если Вы хотите знать полное изложение для того, как этот тип вещи работает (и для всего типа наследования, включая несколько и виртуальное наследование), одним из лучших ресурсов является Stan Lippman "В Модели Объекта C++".

6
ответ дан 4 December 2019 в 06:35
поделиться

Игнорируя аспекты привязки, это не на самом деле компилятор, который определяет это.

Это - время выполнения C++, которое оценивает через vtables и vpointers, что производный объект на самом деле во времени выполнения.

Я настоятельно рекомендую книге Scott Meyer Эффективный C++ для хороших описаний о том, как это сделано.

Даже покрытия, как параметры по умолчанию в методе в производном классе проигнорированы и любые параметры по умолчанию в базовом классе, все еще взяты! Это связывает.

3
ответ дан 4 December 2019 в 06:35
поделиться

Ответить на вторую часть Вашего вопроса: тот адрес, вероятно, не будет иметь v-таблицы в правильном месте, и безумие последует. Кроме того, это не определено согласно стандарту.

1
ответ дан 4 December 2019 в 06:35
поделиться
cout << ((Polygon *)0x12345678)->area() << endl;

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

В C++ Вы не должны использовать старые броски C-стиля как это, необходимо использовать dynamic_cast как так:

Polygon *obj = dynamic_cast<Polygon *>(0x12345678)->area();
ASSERT(obj != NULL);

cout << obj->area() << endl;

dynamic_cast возвратит ПУСТОЙ УКАЗАТЕЛЬ, если данная подсказка не будет допустимым объектом Полигона, таким образом, это будет захвачено УТВЕРЖДЕНИЕМ.

1
ответ дан 4 December 2019 в 06:35
поделиться

Таблицы виртуальной функции. К остроумию оба из Ваших производных объектов Полигона имеют таблицу виртуальной функции, которая содержит указатели функции к реализациям всех их (нестатических) функций; и когда Вы инстанцируете Треугольника, указателя виртуальной функции для области () единицы функциональности к Треугольнику:: область () функция; когда Вы инстанцируете Прямоугольника, область () единицы функциональности к Прямоугольнику:: область () функция. Поскольку указатели виртуальной функции хранятся наряду с данными для объекта в памяти, каждый раз, когда Вы ссылаетесь на тот объект как на Полигон, соответствующая область () для того объекта будет использоваться.

1
ответ дан 4 December 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: