Я в настоящее время разрабатывает язык программирования и мне любопытно, как решить эту проблему:Как вызывается функция в подтипе?
Предположим, что у меня есть класс (или интерфейс) А, который выглядит следующим образом:
class A { // size is 4 bytes
int32 a = 0;
}
и второй класс B, который расширяет его и выглядит следующим образом:
class B extends A { // size is 8 bytes
int32 b = 0;
}
и что у меня есть функция п, что выглядит следующим образом:
int32 f(A first, A second) {
return first.a + second.a;
}
Если я называю это с двумя Bs, однако, second.a не будет находиться в том же месте, что и если бы он был вызван с двумя As, потому что первый параметр сдвинул бы его. Мои текущие мысли для решения этого:
- Запрет параметров неизвестного размера, и заставляя его быть переданы в качестве указателя или ссылки (я думаю, что это то, что делает Rust)
- Дать все следующие информации стек вызовов: указатель на второй, указатель на второй, невариантный размер, первый, второй
- Создание функции для каждого возможного размера первого и второго и определение того, какой вызов вызывать во время компиляции, если известно, или во время выполнения с использованием vtables.
Вторая идея была бы проблемой, поскольку она должна поддерживаться всеми функциями, даже если они редко или никогда не вызываются с использованием подтипа, который неэффективен.
Третья идея потребует создания множества функций (функция, которая принимает 5 параметров, которые могут быть из 20 разных подтипов, потребует создания 100 одинаковых фрагментов кода, если она называется только одной с неизвестным типом params), и для этого потребуется vtable для каждого класса, который использует только одну функцию. Кроме того, функция в уже скомпилированной библиотеке не может использоваться с новым подтипом.
Сочетание 2 и 3 и создание двух версий тех же функций, которые допускают только тип, а другой, который принимает подтипы, также могут решить некоторые из этих проблем.
Мне интересно, есть ли лучшие решения для этого и как реализуют другие языки, такие как C++.
В C++ вы будете * нарезать * объект, то есть объект, который скопирован в стек как параметр, по существу, является первым размером 'sizeof (A)' байта объекта, предоставленного в качестве аргумента. Обычно это рассматривается как опасность перехода по значению. –
Я не уверен, что это правильный сайт SE для этого вопроса, но я не могу думать, куда он должен идти. Возможно CS.SE. –
@KyleStrand: что, если функция вызывает виртуальную функцию на полученном параметре, а функция переопределения использует значение b класса, которое было нарезано? – Runemoro