полиморфизм - это такое языковое средство, когда обращаясь к объекту используя одно и то же имя и одно и то же действие получать разное, в зависимости от того, что там было на самом деле статический полиморфизм это перегрузка функций (a + b имеет разный смысл в зависимости от того, какого типа a и b), tag dispatch динамический полиморфизм - когда определяется какая операция в рантайме

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

виртуальные функции - это runtime явление, а проверка приватности это compile time явление. то, какая именно функция будет выбрана определяется в рантайме и в зависимости от того, что лежит под объектом на самом деле, а легален ли этот вызов определяется в compile time. в compile time компилятор никак не может определить, какая функция будет выбрана. короче говоря приватность зависит только от того, от кого мы вызвались статически

поэтому для примера ниже компилятор не знает, в какую версию в рантайме мы попадём, в приватную или публичную но если бы в бабушке функция была бы приватной, а в маме публичной, то было бы CE, тк с точки зрения компиляции, мы обращаемся к бабушкиной f, которая может быть запрещена для внешних функций

если 2 родителя имеют функцию с одной и той же сигнатурой, но у одного она виртуальная, то у наследника своя функция с такой же сигнатурой будет виртуальной

если 2 родителя имеют функцию с одной и той же сигнатурой и у обоих она виртуальная, то это будет интуитивно работать

абстрактный класс - это такой класс, у которого есть хотя бы один pure virtual метод метод называется pure virtual, если он virtual и написано = 0; pure virtual метод всё равно можно определить абстрактные классы ещё называются интерфейсами нельзя создать объект абстрактного класса

memory layout of polymorphic objects

(не стандартизовано, но база) Application Binary Interface - ABI - бинарный интерфейс того, как компилятор по отношению к ОС и процессору должен располагать

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

memory layout of polymorphic objects with multiple inheritance

memory layout of polymorphic objects with multiple virtual inheritance

diamond problem (ромбовидное наследование) - когда мы 2 раза через разных промежуточных родителей наследуемся от одного и того же класса и в наследнике получается 2 версии предка

способы хранить разные типы в одном векторе:

  • динамический полиморфизм: делаем unique_pointer’ы на интерфейс и складываем в вектор (по простому: складываем указатели на Base)
  • статический полиморфизм: складываем типы в variant и делаем вектор из variant (тк здесь у нас уже разные типы и их не связывает никакой родительский класс)

вместо вектора из variant можно сделать tuple из векторов одного типа, чтоб для определенного типа можно было что-то сделать

virtual functions