класс может наследоваться от структуры, а структура от класса в классе по умолчанию наследование приватное, в структуре публичное приватность никак не влияет на наличие полей в наследнике, они есть всегда, просто могут быть недоступны

модификаторы доступа полей:

protected - этот член класса доступен всем другим членам этого класса, всем друзьям и наследникам private - члены класса доступны только членам класса и друзьям public - доступно всем

модификаторы доступа наследования:

public - все внешние функции имеют доступ к наследуемым полям родителя private - только наследник и его друзья имеют доступ к родительской части protected - только наследник, его наследники и друзья имеют доступ к родительской части

частное предпочтительнее общего методы с таким же именем, как у родителя, затмевают родительский метод также и с полями, поля наследника более локальные Метод класса, если определён полностью внутри класса, помечается inline, это позволяет обходить ODR. Начиная C++17, inline можно использовать и с переменными для обхода ODR. Так, например, можно определять статические поля класса в хедере.

можно привнести protected методы в наследника через using: using Base::protectedMethod; и тогда они будут доступны наравне с методами наследника. таким образом можно из внешних функций обращаться к защищённым полям родителя также можно извне запретить методы родителя, поместив их в приватную область

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

как хранятся в памяти: в порядке объявления, то есть сначала родительские части наличие методов (невиртуальных) не влияет на размер

EBO - Empty Base Optimization если родитель пустой (1б), то ему разрешается ничего не занимать в памяти (0б), тк это не противоречит правилу “у разных объектов разные адреса”

при конструировании сначала полностью создаётся объект родителя можно в конструкторе наследника сначала указать, чем инициализировать поля родителя если не указать, то родитель попытается сконструироваться по умолчанию деструкторы вызываются сначала у наследников, потом у родителей

если у родителя нет конструктора по умолчанию, то придётся самому вызвать другой конструктор Derived(int x) : Base(x), x_(x) {}; так можно вызвать конструктор только ближайшего предка, более дальних можно только при виртуальном наследовании

с С++11 можно наследовать конструкторы, надо написать у Derived using Base::Base; наследуются все конструкторы, кроме конструктора копирования и перемещения

если есть наследник, а функция принимает родителя, то ей можно подсунуть наследника

срезка при копировании (slicing): при отдаче в фунцию, принимающую родителя, наследника по значению, то вызовется конструктор base от derived а если по ссылке, то просто рассматривается наследник, будто бы это родитель

приведение наследника к родителю и обратно: у reinterpret_cast строчка так выглядит для любых типов

static_cast вниз при приватном наследовании невозможен, тк факт наследования скрыт

static_cast от base к derived при виртуальном наследовании невозможен (CE), тк начало виртуального предка не найдём однако можно dynamic_cast (если предок полиморфный)

когда static_cast, dynamic_cast и reinterpret_cast дают разные результаты?

  1. каст вбок (CE, норм работает, UB)
  2. каст вниз при виртуальном наследовании, предок полиморфный (CE, норм, UB)

множественное наследование:

если у объекта 2 родителя, то приведение к родителю также будет работать, адрес начала родительской части может быть сдвинут. пример неявного каста одного указателя к другому, при котором численное значение указателя меняется

можно унаследовать 2 одинаковых поля, но CE будет только при обращении к ним (неоднозначное обращение). также и с методами, но если объявить более локальный метод, то всё норм, он затмит 2 родительских

diamond problem/ромбовидное наследование s.Granny::g - s.g - неоднозначное обращение s.Mom::g - норм

при любом касте к бабушке, например Granny& g= s; - CE по причине ambigouos cast этого можно избежать, сначала скастившись к маме, а потом к бабушке

при вызове бабушкиного метода также CE, ambigouos request, потому что метод может пользоваться полями класса, а непонятно, от какой бабушки достался этот метод

каст вбок запрещен (неизвестен сдвиг)

inacceseble base class (warning)

если унаследовать маму от бабушки и унаследовать сына от мамы и бабушки(2), то получится, что до прямой бабушки(2) нет синтаксиса, чтобы обратится (ну есть, reinterpret_cast и вручную сдвинуть указатель, но это нелегально) виден, доступен, но нельзя обратиться чуть сложнее, чем проблема ромбовидного наследования, но там мы хотя бы имели синтаксис, как обратиться к конктетной бабушке типо s.Mom::g; а здесь ну к бабушке1 также s.Mom::g, а к бабушке2? s.Granny::g снова ambigous

наследование от переменного числа родителей virtual inheritance polymorphism