00:00 Продолжение 4.2 Visibility and accessibility of fields and methods 2:30 этапы перегрузки в наследовании 3:45 добавление в область видимости методов родителя 8:28 пример сокрытия метода родителя через модификатор доступа 12:12 про поля 29:17 4.3 Memory layout, constructors and destructors in case of inheritance 30:48 про размер объектов и выравнивании при наследовании 33:10 размер пустой структуры 35:19 EBO empty base optimization 38:40 про инициализацию и конструкторы 43:45 деструкторы 53:00 про привнесение конструкторов из родителя 1:06:42 4.4 Casts in case of inheritance 1:11:10 slicing
Если в классе Derived есть метод void f(int) и в классе Base такой же, то при использовании using Base::f в Derived, CE не происходит по следующей причине: Методы класса по умолчанию помечаются inline, но это ключевое слово уже не используется для подсказки компилятору о встраивании. Оно позволяет обходить ODR. В таком случае на стадии линковки будет выбрано какое-то одно определение и всё. Начиная с 17 стандарта inline можно использовать и с переменными и тоже для обхода ODR. Так, например, можно определять статические поля класса в хэдере.
Может кто-нибудь объяснить почему в этом коде выводится 1, хотя должно же 2: struct Granny: int x = 1; void f() { std::cout x; } }; struct Mom: Granny { int x = 2; }; int main() { Mom m; m.f(); }
Нет, не должно. С чего бы? Имя x в теле бабушки означает бабушкино x. Компилятор связывает имя x с соответствующей переменной, когда компилирует f. Крутой вопрос на понимание, кстати, спасибо))
Пожалуйста) но он разрушил мое питоновское восприятие мира) В Питоне все хорошо с этим: class Granny: x = 1 def foo(self): print(self.x) class Mom(Granny): x = 2 m = Mom() m.foo() #выводится 2
@@nicholasspezza9449 Как раз-таки в питоне это странно работает. this - это указатель на текущий объект, соответственно тип этого указателя - это тип_объекта*. В данном случае, вы используете this в методе объекта Granny. Значит this имеет тип Granny*. И вызывая this->x вы можете иметь ввиду только тот x, который принадлежит именно Granny. По сути сама Granny не знает кому она станет в будущем родителем и ей не нужно об этом знать.
здравствуйте, Илья! #include class A { protected: int x; }; class B: protected A { public: B(int x): x(x) {} void f() { std::cout x = x, то все окей. вроде почитал несколько ответов на StackOverflow, но полного понимания почему так происходит не получил.. или просто в derived классе бан на инитиализиацию таким образом?
this->x = x; - это не инициализация, а присваивание. Инициализация происходит до входа в тело конструктора, см. лекцию про конструкторы. Наследник сначала должен создать родителя, а потом уже достроить на него свои поля. Как именно может быть создан родитель - определяет сам родитель, а не наследник. Наследник не может говорить родителю, как ему инициализировать его поля при создании. Наследник может только вызывать конструкторы родителя, но не напрямую вмешиваться в логику создания родителя