В этом уроке начнём рассматривать такие особенности ООП как перегрузка операторов. Для начала рассмотрим пример и синтаксис перегрузки, узнаем для чего нужна перегрузка операторов. Первая перегрузка пример которой мы рассмотрим будет перегрузка оператора присваивания. Обращаю ваше внимание на то, что для полного понимания этого вопроса вам необходимо знать что такое конструктор копирования и для чего он нужен.
подскажите пожалуйста, где уроки с 63 по 83? Вы в 83 уже по полной в ООП углубляетесь, а на 63 только подбирались. Думал я дурак, но все обыскал и не нашел(
Честно говоря теперь код стал довольно большим, со всякими конструкторами , деструкторами и перегрузками....и поэтому теперь чтобы нормально разобраться нужно посмотреть на код целиком, а у тебя в окне Студии видна только часть кода и при таком быстром скроллинге разумеется ничего не успеешь рассмотреть, а на паузу ставить тот ещё геморой. Жаль что исходный код теперь недоступен.
Как всегда спасибо за уроки. Для тех кто не понял фишку с тем, зачем нужно возвращать ссылку на объект. Уравнение с = b = a в оригинале выглядит так: c.operator=(b.operator=(a)); то есть, сначала в объект b мы присваиваем объект a, и чтобы мы могли присвоить сразу же в объект c наш объект b, наша функция присваивания a в b должна вернуть ссылку на этот объект b, потому что оператор присваивания c не может работать с функцией оператора присваивания a в b, если эта функция не возвращает необходимую ссылку на объект b. Сам пытался додуматься очень долго, для тех, кто не понял, попробуйте прочитать моё объяснение, может поймете лучше.
Ну да всё так. Оператор = принимает ссылку на объект, а возвращает void, а надо чтобы возвращал тоже ссылку на такой же объект. На самом деле вернуть надо не ссылку, а объект или объект по ссылке.
Потрясающие уроки Жонглировать объектами и конструкторами гораздо сложнее чем в java Но, чёрт возьми, это же ОФИГЕННО Чём больше язык предоставляет способов прострелить себе ногу - тем он круче и мощнее
Artem Kuleshov ты меня смотивировал я думал я один такой с первого раза не вьезжаю мол значит не мое это и я туп, думал на 82 83 остановиться бросить, думал у всех идет по маслу, один урок за др, оказ надо пересмотреть, если не 2раза так еще, значит я один из вас, попробую заново
@@Wardriving666 Конечно не один, Сережа мощно буксанул с обьяснениями как только добрался до чего то сложного. Любитель, что вы хотите?! Но хорошо что хоть такой есть. Часто любитель работает лучше не мотивированного профессионала
до какого-то момента мне удавалось проходить и усваивать 2-3 урока за день, а теперь трешак начался - на 82 урок почти 3 дня🤯🤯🤯, но я пока не сдаюсь. Огромная благодарность Сергею, что может донести инфу даже такому тугодуму - как я😎
Было тяжко понять урок, бросил все, пошел гулять, чуть позже вернулся, посмотрел и понял все )). Чем дальше тем сложнее, так кажется, на самом деле иногда надо просто отвлечься/отдохнуть.
Тут в начале, на 3:00, есть большая неточность. Автор говорит «объект А будет думать, что он объект Б». (по описанию похоже на работу указателей, и это запутывает) Правильно: ОТДЕЛЬНЫЕ ПОЛЯ в объекте А, которые являются указателями, получат те же адреса которые в этих же полях-указателях в объекте Б. Объекты классов - это самостоятельные единицы, у каждого объекта свои поля. Не может быть один объект порван между двумя разными переменными. Бывают &ссылки , но ссылка - это дополнительное имя переменной, а не собственно переменная. Если присвоить один объект другому: а = б; //и если они одного класса , то 1) указатели в «а» получат те же адреса, что указатели в «б» 2) остальные поля в «а» получат те же значения, что эти же поля в «б» По причине 1) вот здесь 4:52 показываются одинаковые адреса. Среда показывает адрес указателя *data , который содержится в каждом объекте. (Почему показывается именно он? Потому что он - самый первый в каждом объекте. Среда берёт ближайшее к началу поле в объекте, и в данном случае это поле - указатель *data.) Это называют «поверхностное копирование» (shallow copy), то есть когда оператор присваивания или конструктор копирования даёт указателям адрес на ту же память, что и в исходном объекте. В Си++ в классах оператор присваивания и конструктор копирования по умолчанию работают так (если их не переопределить). «Глубокое копирование» (deep copy) - это когда оператор присваивания или конструктор копирования выделяет новую память. То есть если в исходном объекте есть указатель на память, выделенную через "new", то оператор присваивания или конструктор копирования выделяет новую память для указателя в том объекте, куда копируются данные из исходного объекта.
@@misha2993 Другими словами. Автор говорит «объект А будет думать, что он объект Б». Правильно: ОТДЕЛЬНЫЕ ПОЛЯ в объекте А, которые являются указателями, получат те же адреса которые в этих же полях в объекте Б.
у нас в универе этот материал неделю объясняют и то супер коряво и большинство просто зубрят не понимая что делают, здесь хватило 2 раза пересмотреть и вроде бы понятно все. огромное спасибо за труды, интернет будет тебя помнить долго!
Спасибо за урок)) Очень не хватает задач! Я лучше усваиваю материал когда записываю информацию или работаю на практике(как и многие, наверно), поэтому пока нет задач я каждый сложный урок конспектирую.)))
Очень спасибо Сергею за прекрасные уроки! Вдвойне приятно, что поставив видео на паузу где-то посередине, я понял , что смогу перегрузить оператор сам и сделал это.
Спасибо земеля! Очень нужные уроки, я надеюсь. Был бы кто-то другой на твоём месте, то давно бы уже бросил изучать. На самом деле мозг уже отключается для восприятия информации. Испробовал методы заставить мозг работать,-гуляние на свежем воздухе, кофе, физ.зарядка, но чувствую пропадает желание к обучению. Какие способы себя заставить можете посоветовать, -ведь нежелательно делать большой перерыв, так как можно забыть чему научился.
Лучший способ заставить себя учиться- Желание. А если его нет, то ищи способы его культивировать. Я смотрел разные фильмы, музыку, искал плюсы в чём-то и втягивался. В итоге, когда желание есть ,можно шпрехать не на голом энтузиазме и силе воли, а на нескончаемом генераторе энергии- Желании)
Обычно в реализации оператора присваивания также проверяют, происходит ли самоприсваивание (то есть, this и &other указывают на один и тот же объект). Это позволяет избежать ненужных операций. Это может выглядеть так: if (this == &other) { return *this; } Эту проверку можно вставить в начале метода.
Вот пример улучшеного кода: Human& operator=(const Human& other) { if (this == &other) { return *this; // Проверка на самоприсваивание } cout data = new int[other.size]; for (int i = 0; i < other.size; i++) { this->data[i] = other.data[i]; } return *this; }
Когда смотрю твои уроки чувствую себя рекурсивной функцией, потому что ,когда ты говоришь мы это проходили в прошлом уроке я сразу на прошлый урок переключаюсь, а там я ничего не понимаю, слышу ту же фразу и также переключаюсь на прошлый урок и так получается рекурсия.
В этом случае все понятно описано. Но есть масса других случаев и операторов, со своей спецификой перегрузки. Нужно больше примеров по этой теме, перегрузки.
Останавливаюсь тут, основные моменты языка вроде как понял, а пока пойду на пайтон. Конечно, не собираюсь бросать этот язык, просто немного огонек подсбавлю, 15 видео в день по-моему многовато, буду 1-2 усваивать. :) А пока на фриланс!)
Спасибо за урок! Не понял только зачем делать проверку указателя data на nullptr, ведь ничего не произойдет если мы вызовем delete указателя, указывающего на nullptr?
4:19 Не очень понял, почему так. Если мы присваиваем одному объекту другой, то копируются только значения полей. По крайней мере, "this" у них отличаются, и, меняя одно из полей в копии, не меняется поле в оригинале. Так почему же объект "a" начинает думать, что он и есть объект "b"?
Я понял (я не уверен), что это из-за работы с динамической памятью, т.к. data в private имеет указатель(*). И формально, мы передаём данные по данному указателю (ну, другое само собой придётся тоже делать под такой тип, чтобы работало, я про всё в классе)
Проверка на delete nullptr не нужна, т.к. delete в этом случае не предпримет никаких действий. А вот проверить на случай: MyClass A; A = A; вполне стоит, без проверки присвоения самого себе произойдет неприятная ситуация потери данных...
А если при присваивании объектов друг другу всё равно им присваиваются разные адреса даже без перегрузки оператора, это новые версии компилятора или Visual Studio 17 так делает?
Я не совсем понимаю, почему мы возвращаем ссылку на объект, а не сам объект. Объясню что я имею в виду. Когда мы присваиваем объект a в объект b оператором b = a; мы фактически вызываем функцию b.operator=(a); То есть мы в качестве аргумента используем САМ ОБЪЕКТ а. А уж в самой функции используется его ссылка с помощью оператора &. Это понятно. Но если мы вернём из функции ссылку на объект b, то функция c = b будет принимать не САМ ОБЪЕКТ b, а ссылку на него. И в функции будет использоваться ссылка на ссылку. Разве не так? Пример (упрощенный, но с той же идеей): int& Foo(int value) { return value; } // функция возвращает просто ссылку тогда почему же в main мы МОЖЕМ написать так: int a = 2; int b; b = Foo2(a); Как это так мы в b присваиваем ссылку на a, если b типа int, а не int* ?
Я не уверен, что до конца понял, но попробую объяснить это на том уровне, на котором всё-таки дошло. Если вспомнить урок про ссылки, то там говорилось, что ссылочный тип не требует разыменования. Соответственно, написать b = Foo2(a); это то же самое, что и написать int& c = Foo2(a); b = c; В последней строчке мы хоть и работаем с ссылкой, но никаких операторов к ней не применяем. Т.к. запись "c" уже подразумевает только значение, лежащее по этому адресу. Так и в примере с объектами. Мы возвращаем ссылку на объект b после первой операции присваивания, а потом уже эта ссылка, как результат функции, никаких операторов разыменования не требует, поэтому мы спокойно используем её в функции. Хотя всё-равно получается в функции ссылка на ссылку, но это, я так понимаю, нормально. Кстати, объяснять что-то кому-то другому бывает полезно для собственного понимания вопроса.
@@almatytelecom1 я изучил и все равно не понимаю почему у автора в конце Myclass & operator= вместо просто Myclass operator=? Мы же все равно возвращаем САМ объект *this...
Обращение к автору. Объект a не будет думать, что он объект b. Потому что, присваивание идёт только по значению, а адреса у обеих переменных, разные так и остаются как и были изначально. Посмотрите, что вы преподаёте с 4 м. 20 сек. ролика.
правильно говоришь по значению...все верно, только эти значения адреса объектов...адреса у a и b останутся разные но если значения их станут равны ссылаться они будут уже на один объект...
Спасибо! Я даже понял почему мы ссылку возвращаем ! Очень круто . Спасибо вам огромное .(Вопрос)Мы можем с помощью delete удалить данные из статической памяти ?
я понял что делает конструктор копирования. я понял зачем он копирует объект при передачи его в функцию(потому что передаём его по значению) Я НЕ понял зачем он вызывается при возврате объекта из функции. Зачем создаётся временный объект для хранения полей возвращаемого объекта? объясните пожалуйста!!
потому что передача параметров в функцию и обратно из нее производится по значению(в обычном случае без использования указателей и ссылок). А понятие по значение и есть копирование.
Я так полагаю, что мы возвращаем значение из-за того, что в итоге при присваивании объекта b к c оператор у нас не будет перегружен, если не вернется ссылка на объект
А как тогда поступить, если мы создаем объект класса в динамической памяти, то есть, допустим, у нас класс, содержащий одно поле - имя, мы создадим два объекта, в классе реализуем перегрузку оператора присвоения, присвоим и как дальше? Как очистить область памяти? MyName* person_1 = new MyName(); MyName* person_2 = new MyName("Nik"); person_1 = person_2; delete person_2; delete person_1; //реализация перегрузки оператора присвоения: MyName& operator = (const MyName& other) { cout
У Вас произойдет утечка пямяти и программа вылетит с ошибкой. Вы один и то же объект удалаяте два раза. Никакой оператор присваивания у Вас вызываться не будет. Вы просто прсвоили одному указателю значение другого указателя. Нужно: *person_1 = *person_2;
потому что передача в функцию и возврат из нее в обычном случае происходит по значению. И при передаче по значению происходит копирование из внешних переменных во внутренние, и наоборот при выходе из функции копирование из внутренних во внешние. p.s.( под обычным случаем я понимаю вызов функции без использования указателей и ссылок)
люди добрые подскажите пожалуйста!Для чего мы присваиваем (this->Size = other.Size;) Ведь в дальнейшем мы будем обращаться к объекту (other.Size) например при выделении памяти для дин.масива (this->data = new int[other.Size];) или когда мы перебираем массив ( for (int i = 0; i < other.Size; i++) ) Для вас может показаться вопрос глупым но я не могу понять для чего мы выполняем присваивание
Проверка на nullptr при очистки памяти с помощью delete[] не нужна, delete[] в C++ (в отличии от free в Си) может спокойно сжирать nullptr и никаких утечек не будет👌
Вот этот конструктор "MyClass(const MyClass &other)" так выносит мозг наличием ссылки &other. Вроде всё знакомо, но в целом почему после вызова "MyClass b = a;" идёт 2 перегрузка сложно.
Может кто то к примеру сказать где это используется, а то уже нить потерял зачем она используется, тока надо пример из реальной жизни, что писать чтобы работало понятно, нужен просто пример
Понял суть, деталицазцию под капотом не всю. Меня терзает только один вопрос - Зачем все это нужно? Практическое применение, жаль что не приводятся примеры этого.
Хочу добавить один момент, который может быть не очевиден. Рассмотрим работу оператора присваивания ПОСЛЕ того, как Сергей дополнил его возвращаемым значением *this 1) Когда выполняется инструкция a = b; значение *this возвращается, но НЕ ИСПОЛЬЗУЕТСЯ. 2) Когда выполняется инструкция c=a=b; - значение *this возвращается в первом присвоении, но НЕ используется, но, используется во втором присвоении, чтоб присвоить резльтат переменной с. Для более простого понимания можно написать так: с=(a=b). Не понимаю почему так, но так. Наверно я что-то паропустил в самом начале.
Проще наверно не копировать объект в объект, дабы не парится с перегрузкой методов копирования и присваивания. А то сегодня это один объект, завтра другой, а про то что надо внести изменения еще куда-то никто потом и не вспомнит.
А почему бы нам не возвращать &*this из перегруженого оператора? Если я правильно понимаю, то this - указатель объекта на самого себя, *this - сам объект, а &*this - ссылка на этот объект.
@@aviator1472 Наверное по сути ссылка там и не нужна, но только потому, что этот перегруженный оператор и так принимает объект по ссылке (в его аргументах задано)
Конструктор срабатывает один раз при создании экземпляра класса. Затем ты можешь присвоить отдельным паблик полям новые значения (тут нет никакого конструктора), ну либо же присвоить новый объект. Как раз для этого мы и перегрузили оператор присваивания.
c.operator=(a.operator=(b)); Вот, наконец понял Когда для "c" вызывается перегруженный оператор, мы передаём в его аргументы "a", который в свою очередь должен сначала отработать свою перегруженную функцию и вернуть свой результат работы, поэтому он возвращает в "c" - "return *this;"(себя)
Я не понимаю когда мы перегружаем классы, то вводя параметры 10, 2, 5 и т.д они подходят под все перегрузки и по этому всё выводится на экран? А a = b и c = a = b это просто примеры как это выглядит?
В этом уроке начнём рассматривать такие особенности ООП как перегрузка операторов. Для начала рассмотрим пример и синтаксис перегрузки, узнаем для чего нужна перегрузка операторов. Первая перегрузка пример которой мы рассмотрим будет перегрузка оператора присваивания. Обращаю ваше внимание на то, что для полного понимания этого вопроса вам необходимо знать что такое конструктор копирования и для чего он нужен.
привет. только ты не рассказал почему вызывается конструктор копирования после команды return *this ! давай раз уже начал!
@@eninyri никакой там конструктор копирования не вызывается
подскажите пожалуйста, где уроки с 63 по 83? Вы в 83 уже по полной в ООП углубляетесь, а на 63 только подбирались. Думал я дурак, но все обыскал и не нашел(
Чувствую, нужно покупать вентилятор по мощнее, мой мозг перегрелся)) Возврат ссылки на объект меня просто убил, пытаюсь переварить этот урок))
Честно говоря теперь код стал довольно большим, со всякими конструкторами , деструкторами и перегрузками....и поэтому теперь чтобы нормально разобраться нужно посмотреть на код целиком, а у тебя в окне Студии видна только часть кода и при таком быстром скроллинге разумеется ничего не успеешь рассмотреть, а на паузу ставить тот ещё геморой. Жаль что исходный код теперь недоступен.
1:15 "А" равно, ну к примеру, 5.
а=2
Иван Гончаренко И так по жизни. А потом ищешь что не работает :D
Ну ошибся человек, с кем не бывает. Тем более это обычная интовая переменная.
@@adiletastana2781 однажды из-за одного бита, не байта, а бита, случилось авиакрушение
@@dmytrolytvynenko6537 вашего пукана?)
@@АртемНезабудкин-п1г авиа
Как всегда спасибо за уроки. Для тех кто не понял фишку с тем, зачем нужно возвращать ссылку на объект. Уравнение с = b = a в оригинале выглядит так:
c.operator=(b.operator=(a)); то есть, сначала в объект b мы присваиваем объект a, и чтобы мы могли присвоить сразу же в объект c наш объект b, наша функция присваивания a в b должна вернуть ссылку на этот объект b, потому что оператор присваивания c не может работать с функцией оператора присваивания a в b, если эта функция не возвращает необходимую ссылку на объект b. Сам пытался додуматься очень долго, для тех, кто не понял, попробуйте прочитать моё объяснение, может поймете лучше.
Ну да всё так. Оператор = принимает ссылку на объект, а возвращает void, а надо чтобы возвращал тоже ссылку на такой же объект. На самом деле вернуть надо не ссылку, а объект или объект по ссылке.
Спасибо!, теперь понял более подробно.
Может я тупой, но я не понял. Много букаф
@@doge8633 Жиза
Слава Богу, заглянул в комменты, а то еще бы день провозился.Спасибо!
Потрясающие уроки
Жонглировать объектами и конструкторами гораздо сложнее чем в java
Но, чёрт возьми, это же ОФИГЕННО
Чём больше язык предоставляет способов прострелить себе ногу - тем он круче и мощнее
Тебе хорошо зайдет ассемблер :)
Резвись наслаждайся :)
А понимаю почему люди придумывают все более высокие по уровню языки...
то чувство теплоты в черепной коробке, свидетельствующей о перегреве мозга...но снова на третий раз "зашло всё" до каждого символа! Спасибо.
Artem Kuleshov ты меня смотивировал я думал я один такой с первого раза не вьезжаю мол значит не мое это и я туп, думал на 82 83 остановиться бросить, думал у всех идет по маслу, один урок за др, оказ надо пересмотреть, если не 2раза так еще, значит я один из вас, попробую заново
@@nurbolatnurguatov2407 Ты не один такой=)
@@Wardriving666 Конечно не один, Сережа мощно буксанул с обьяснениями как только добрался до чего то сложного.
Любитель, что вы хотите?! Но хорошо что хоть такой есть. Часто любитель работает лучше не мотивированного профессионала
@@nurbolatnurguatov2407 До какого урока дошел, или прошел все? Я не однократно сдавался на каком-то этапе, теряя нить понимания.
до какого-то момента мне удавалось проходить и усваивать 2-3 урока за день, а теперь трешак начался -
на 82 урок почти 3 дня🤯🤯🤯, но я пока не сдаюсь. Огромная благодарность Сергею, что может донести инфу даже такому тугодуму - как я😎
ты просто машина, я тут как улитка сижу и въежаю,
спасибо за уроки
Пожалуйста!
только Бьёрн Страуструп понял этот урок ))
Было тяжко понять урок, бросил все, пошел гулять, чуть позже вернулся, посмотрел и понял все )). Чем дальше тем сложнее, так кажется, на самом деле иногда надо просто отвлечься/отдохнуть.
да, согласен
спасибо, согласен полностю
Жиза. Только у меня сначала возникает желание умереть, потом приходит осознание, что прошла неделя и уже потом принятие
мне это далось гораздо легче конструктора копирования
отдых - тоже часть работы
Все видео более информативные и понятные, чем наши лекции в университете. Большое спасибо!
Пожалуйста!
Тут в начале, на 3:00, есть большая неточность.
Автор говорит «объект А будет думать, что он объект Б». (по описанию похоже на работу указателей, и это запутывает)
Правильно: ОТДЕЛЬНЫЕ ПОЛЯ в объекте А, которые являются указателями, получат те же адреса которые в этих же полях-указателях в объекте Б.
Объекты классов - это самостоятельные единицы, у каждого объекта свои поля. Не может быть один объект порван между двумя разными переменными. Бывают &ссылки , но ссылка - это дополнительное имя переменной, а не собственно переменная.
Если присвоить один объект другому:
а = б; //и если они одного класса
, то
1) указатели в «а» получат те же адреса, что указатели в «б»
2) остальные поля в «а» получат те же значения, что эти же поля в «б»
По причине 1) вот здесь 4:52 показываются одинаковые адреса. Среда показывает адрес указателя *data , который содержится в каждом объекте. (Почему показывается именно он? Потому что он - самый первый в каждом объекте. Среда берёт ближайшее к началу поле в объекте, и в данном случае это поле - указатель *data.)
Это называют «поверхностное копирование» (shallow copy), то есть когда оператор присваивания или конструктор копирования даёт указателям адрес на ту же память, что и в исходном объекте. В Си++ в классах оператор присваивания и конструктор копирования по умолчанию работают так (если их не переопределить).
«Глубокое копирование» (deep copy) - это когда оператор присваивания или конструктор копирования выделяет новую память. То есть если в исходном объекте есть указатель на память, выделенную через "new", то оператор присваивания или конструктор копирования выделяет новую память для указателя в том объекте, куда копируются данные из исходного объекта.
Спасибо, что расписал это, братан! Тоже смутило это, уже собирался проект собирать свой и проверять
спасибо а то и вправду запутало
Да храни тебя араб в подвале! Выручил
Нихрена не понял, но понял, что автор что-то напутал
@@misha2993 Другими словами.
Автор говорит «объект А будет думать, что он объект Б».
Правильно: ОТДЕЛЬНЫЕ ПОЛЯ в объекте А, которые являются указателями, получат те же адреса которые в этих же полях в объекте Б.
Все бы препады так же доходчиво объясняли! На паре часто фиг поймёшь, что зачем и почему. После твоих уроков, всё расставляется по полочкам!
Спасибо тебе! Годы идут, а материал по-прежнему очень полезен, нигде не встречал более понятного объяснения!!!
у нас в универе этот материал неделю объясняют и то супер коряво и большинство просто зубрят не понимая что делают, здесь хватило 2 раза пересмотреть и вроде бы понятно все. огромное спасибо за труды, интернет будет тебя помнить долго!
Это такое удовольствие понимать, что происходит. Спасибо за уроки
Большое спасибо за уроки! Все на высшем уровне.
a равно, к примеру 5. а = 2. Лайк однозначно)))
Спасибо, что ты есть
немного сложно,но интересно! Спасибо за урок!!!
Спасибо за разъяснение отличий конструктора копирования и оператора присваивания!
Как ни странно, понял с первого раза) спасибо за предыдущий урок)
Это уже второй урок который я с первого раза не понимаю...Ну ничего,раза два ещё посмотрю и точно пойму.Спасибо вам:)
Спасибо за урок)) Очень не хватает задач! Я лучше усваиваю материал когда записываю информацию или работаю на практике(как и многие, наверно), поэтому пока нет задач я каждый сложный урок конспектирую.)))
Могу тебе свои лабораторки скидывать
Бро, мне тоже скинь лабы. Заранее спасибо)
@@ВолодяСвіргун-х5д Братан,скинь пж
@@Роман-т5е6с спустя 3 года)))) ну если скинут то и мне скинь)
@@ВолодяСвіргун-х5д Спустя 4 года (кто больше?) И мне скинь плиз!!!
Сложно, но я понял. Спасибо больше, а то в универе пробежались быстро ничего не понятно объяснять не хотят. Ну и как обычно коммент для продвижения
Большое спасибо вам за урок и прекрасное пояснение, Сергей!
Очень хорошие уроки, понятным языком! Большое спасибо!
Спасибо за уроки!! После предыдущего было очень просто, весь код практически смог сам написать, ставя на паузу, только с if не додумался)
я рад тому что вы есть этот и прошлый урок я смотрел 5 раз и едва смог его осилить спасибо вам от простого школьника
Круто и наглядно сделано! Правильная подача для новичкои. Проблема многих книг - это завышенная сложность синтаксиса сбивающая новичков.
Привет, почему у конструктора и оператора адреса похожи? 18:15
Очень спасибо Сергею за прекрасные уроки! Вдвойне приятно, что поставив видео на паузу где-то посередине, я понял , что смогу перегрузить оператор сам и сделал это.
Привет, почему у конструктора и оператора адреса похожи? 18:15
Спасибо за урок.
как раз до этого урока гуглил как сделать свои операторы, а то в питоне такое можно сделать, значит и тут можно. Наконец-то я до этого дошел)
И какая понял что к чему?
@@frosten5746 да
#перегрузкаоператоров #ООП #SimpleCode #урокипрограммирования
Сколько уже смотрю уроки на этом канале, и только сейчас заметил, что на фоне играет жесткий рок)
Все понял , после пред идущего урока , этот урок сразу отлично понял , спасибо Серега за тщательное разъяснение.
Спасибо, всё просто и интересно!
Сурс урока. Может кому надо будет...
#include
#include
using namespace std;
class Point
{
private:
int x;
int y;
public:
Point()
{
x = 0;
y = 0;
cout
Спасибо большое!
+++
спасибо
+
святой человек
Спасибо земеля! Очень нужные уроки, я надеюсь. Был бы кто-то другой на твоём месте, то давно бы уже бросил изучать. На самом деле мозг уже отключается для восприятия информации. Испробовал методы заставить мозг работать,-гуляние на свежем воздухе, кофе, физ.зарядка, но чувствую пропадает желание к обучению. Какие способы себя заставить можете посоветовать, -ведь нежелательно делать большой перерыв, так как можно забыть чему научился.
Лучший способ заставить себя учиться- Желание. А если его нет, то ищи способы его культивировать.
Я смотрел разные фильмы, музыку, искал плюсы в чём-то и втягивался. В итоге, когда желание есть ,можно шпрехать не на голом энтузиазме и силе воли, а на нескончаемом генераторе энергии- Желании)
Весьма хорошая подача материала, Вы большой молодец!
со второй попытки понял спасибо за урок
Обычно в реализации оператора присваивания также проверяют, происходит ли самоприсваивание (то есть, this и &other указывают на один и тот же объект). Это позволяет избежать ненужных операций. Это может выглядеть так:
if (this == &other) {
return *this;
}
Эту проверку можно вставить в начале метода.
Вот пример улучшеного кода:
Human& operator=(const Human& other)
{
if (this == &other) {
return *this; // Проверка на самоприсваивание
}
cout data = new int[other.size];
for (int i = 0; i < other.size; i++) {
this->data[i] = other.data[i];
}
return *this;
}
Когда смотрю твои уроки чувствую себя рекурсивной функцией, потому что ,когда ты говоришь мы это проходили в прошлом уроке я сразу на прошлый урок переключаюсь, а там я ничего не понимаю, слышу ту же фразу и также переключаюсь на прошлый урок и так получается рекурсия.
А потом переполнение стека...
Это не рекурсия, это просто реверс
В этом случае все понятно описано.
Но есть масса других случаев и операторов, со своей спецификой перегрузки.
Нужно больше примеров по этой теме, перегрузки.
Всё очень понятно и подробно расписано. Большое спасибо!
Спасибо за уроки!!!!!!!
Останавливаюсь тут, основные моменты языка вроде как понял, а пока пойду на пайтон. Конечно, не собираюсь бросать этот язык, просто немного огонек подсбавлю, 15 видео в день по-моему многовато, буду 1-2 усваивать. :) А пока на фриланс!)
Я уже месяца 3 по одному видео смотрю. Так легче усваивать. Все не запомнишь.
У меня перегрузка мозгов
Невероятно спокойно и доходчиво. Курс ООП с универа за месяц у тебя прошёл за 10 часов :)
не одно и то же?
лучший из лучших
Привет, почему у конструктора и оператора адреса похожи? 18:15
Да тут я поплыл ,вроде как все понял но не точно. Спасибо
Спасибо! идём дальше
Чихнул когда сказал что его зовут Сергей - значит правда =)
Братан, Это очень круто!!!!
Спасибо за урок!
єто как в сказке Алиса В Стране Чудес - кролик откусил сам себе свою же голову :-)
привет из 2023, спасибо большое за уроки!
Спасибо за урок! Не понял только зачем делать проверку указателя data на nullptr, ведь ничего не произойдет если мы вызовем delete указателя, указывающего на nullptr?
Блин, весь урок понимал-понимал, в последние 3 минуты всё сломалось)))
Ёкарный бабай, тоже самое, но я сонный ночью посмотрел
вечный курс
попробую угадать досмотрев до 10:16 что должен возвращать указатель на то куда присваиваем :)
4:19 Не очень понял, почему так.
Если мы присваиваем одному объекту другой, то копируются только значения полей. По крайней мере, "this" у них отличаются, и, меняя одно из полей в копии, не меняется поле в оригинале.
Так почему же объект "a" начинает думать, что он и есть объект "b"?
Я понял (я не уверен), что это из-за работы с динамической памятью, т.к. data в private имеет указатель(*). И формально, мы передаём данные по данному указателю (ну, другое само собой придётся тоже делать под такой тип, чтобы работало, я про всё в классе)
потому что ты указатели присваиваешь друг другу. И указатели становятся одинаковыми, т.е. начинают указывать на одну и ту же память.
Проверка на delete nullptr не нужна, т.к. delete в этом случае не предпримет никаких действий. А вот проверить на случай:
MyClass A;
A = A;
вполне стоит, без проверки присвоения самого себе произойдет неприятная ситуация потери данных...
Черт) сложновато. Но все равно спасибо.
23:05 для чего он поставил & между MyClass и operator ? буду очень благодарен за ответ.
он же объяснил типо))) сам не понимаю
@@mashauser1812 самое интересное, что я смог разобраться...
@@gans0072 ну и почему?
@@peaktop3286 я уже забыл..
Что-то вроде указатель на указатель
@@gans0072 bruh ☠️
А если при присваивании объектов друг другу всё равно им присваиваются разные адреса даже без перегрузки оператора, это новые версии компилятора или Visual Studio 17 так делает?
Тот же вопрос хотя я сижу в VS 2017 года.
Я не совсем понимаю, почему мы возвращаем ссылку на объект, а не сам объект. Объясню что я имею в виду.
Когда мы присваиваем объект a в объект b оператором b = a; мы фактически вызываем функцию b.operator=(a); То есть мы в качестве аргумента используем САМ ОБЪЕКТ а. А уж в самой функции используется его ссылка с помощью оператора &. Это понятно.
Но если мы вернём из функции ссылку на объект b, то функция c = b будет принимать не САМ ОБЪЕКТ b, а ссылку на него. И в функции будет использоваться ссылка на ссылку. Разве не так?
Пример (упрощенный, но с той же идеей):
int& Foo(int value)
{
return value;
}
// функция возвращает просто ссылку
тогда почему же в main мы МОЖЕМ написать так:
int a = 2;
int b;
b = Foo2(a);
Как это так мы в b присваиваем ссылку на a, если b типа int, а не int* ?
Я не уверен, что до конца понял, но попробую объяснить это на том уровне, на котором всё-таки дошло. Если вспомнить урок про ссылки, то там говорилось, что ссылочный тип не требует разыменования. Соответственно, написать
b = Foo2(a);
это то же самое, что и написать
int& c = Foo2(a);
b = c;
В последней строчке мы хоть и работаем с ссылкой, но никаких операторов к ней не применяем. Т.к. запись "c" уже подразумевает только значение, лежащее по этому адресу.
Так и в примере с объектами. Мы возвращаем ссылку на объект b после первой операции присваивания, а потом уже эта ссылка, как результат функции, никаких операторов разыменования не требует, поэтому мы спокойно используем её в функции.
Хотя всё-равно получается в функции ссылка на ссылку, но это, я так понимаю, нормально.
Кстати, объяснять что-то кому-то другому бывает полезно для собственного понимания вопроса.
изучи конкретно , что такое ссылка и ты поймешь.
@@almatytelecom1 я изучил и все равно не понимаю почему у автора в конце Myclass & operator= вместо просто Myclass operator=? Мы же все равно возвращаем САМ объект *this...
@@aviator1472 да дурдом тут какой-то
Спасибо тебе !!!
Привет
Обращение к автору. Объект a не будет думать, что он объект b. Потому что, присваивание идёт только по значению, а адреса у обеих переменных, разные так и остаются как и были изначально. Посмотрите, что вы преподаёте с 4 м. 20 сек. ролика.
правильно говоришь по значению...все верно, только эти значения адреса объектов...адреса у a и b останутся разные но если значения их станут равны ссылаться они будут уже на один объект...
Спасибо! Я даже понял почему мы ссылку возвращаем ! Очень круто . Спасибо вам огромное .(Вопрос)Мы можем с помощью delete удалить данные из статической памяти ?
И почему мы возвращаем ссылку? Для чего вообще нам эта ссылка если мы возвращаем *this тоесть тот же объект..
Подскажите, какой комбинацией клавиш можно быстро закомментировать код, как на видео в момент 6:47
Узнали? Можно мне тоже узнать?
@@RayTracingX не актуально?
я понял что делает конструктор копирования.
я понял зачем он копирует объект при передачи его в функцию(потому что передаём его по значению)
Я НЕ понял зачем он вызывается при возврате объекта из функции.
Зачем создаётся временный объект для хранения полей возвращаемого объекта?
объясните пожалуйста!!
потому что передача параметров в функцию и обратно из нее производится по значению(в обычном случае без использования указателей и ссылок). А понятие по значение и есть копирование.
то есть, как я понимаю мы перегрузили оператор равно так, чтобы он выполнял функцию конструктора копирования?
Я так полагаю, что мы возвращаем значение из-за того, что в итоге при присваивании объекта b к c оператор у нас не будет перегружен, если не вернется ссылка на объект
А как тогда поступить, если мы создаем объект класса в динамической памяти, то есть, допустим, у нас класс, содержащий одно поле - имя, мы создадим два объекта, в классе реализуем перегрузку оператора присвоения, присвоим и как дальше? Как очистить область памяти?
MyName* person_1 = new MyName();
MyName* person_2 = new MyName("Nik");
person_1 = person_2;
delete person_2;
delete person_1;
//реализация перегрузки оператора присвоения:
MyName& operator = (const MyName& other) {
cout
У Вас произойдет утечка пямяти и программа вылетит с ошибкой. Вы один и то же объект удалаяте два раза. Никакой оператор присваивания у Вас вызываться не будет. Вы просто прсвоили одному указателю значение другого указателя.
Нужно: *person_1 = *person_2;
@@svvonline1 Это понятно. Но вопрос то был о другом...
6:48 подскажите, пожалуйста, каким сочетанием также комментировать
нашел, Ctrl+Shift+/
В 145 строке наверно можно уже писать не "other.Size", а просто "Size"? 19:38
Угу
привет. только ты не рассказал почему вызывается конструктор копирования после команды return *this ! давай раз уже начал!
потому что передача в функцию и возврат из нее в обычном случае происходит по значению.
И при передаче по значению происходит копирование из внешних переменных во внутренние, и наоборот при выходе из функции копирование из внутренних во внешние.
p.s.( под обычным случаем я понимаю вызов функции без использования указателей и ссылок)
люди добрые подскажите пожалуйста!Для чего мы присваиваем (this->Size = other.Size;) Ведь в дальнейшем мы будем обращаться к объекту (other.Size) например при выделении памяти для дин.масива (this->data = new int[other.Size];) или когда мы перебираем массив ( for (int i = 0; i < other.Size; i++) )
Для вас может показаться вопрос глупым но я не могу понять для чего мы выполняем присваивание
Проверка на nullptr при очистки памяти с помощью delete[] не нужна, delete[] в C++ (в отличии от free в Си) может спокойно сжирать nullptr и никаких утечек не будет👌
думаю еще надо учесть момент a = a;
this в помощь
@@faustomendez6567 хорош
@@faustomendez6567 а причем тут this?
Вот этот конструктор "MyClass(const MyClass &other)" так выносит мозг наличием ссылки &other. Вроде всё знакомо, но в целом почему после вызова "MyClass b = a;" идёт 2 перегрузка сложно.
Внимательнее смотреть и слушать надо
@@sleepyNovember_project это очевидно. Но не только.
@@nikitasuyazov2060 ну как, уже понял? :)
@@sleepyNovember_project уже понял)
@@nikitasuyazov2060 замечательно
Спасибо!
Красава!
Круто!
Что означает в сроке this->Size = other.size, зачем там точка "other.Size"? и что она означает?
Может кто то к примеру сказать где это используется, а то уже нить потерял зачем она используется, тока надо пример из реальной жизни, что писать чтобы работало понятно, нужен просто пример
Понял суть, деталицазцию под капотом не всю. Меня терзает только один вопрос - Зачем все это нужно? Практическое применение, жаль что не приводятся примеры этого.
Удобство, но это если умеренно применять. В перегрузках с выделением памяти вообще специфика жëсткая, это скорее для прошареных тема
спасибо)
Хочу добавить один момент, который может быть не очевиден.
Рассмотрим работу оператора присваивания ПОСЛЕ того, как Сергей дополнил его возвращаемым значением *this
1) Когда выполняется инструкция a = b; значение *this возвращается, но НЕ ИСПОЛЬЗУЕТСЯ.
2) Когда выполняется инструкция c=a=b; - значение *this возвращается в первом присвоении, но НЕ используется, но, используется во втором присвоении, чтоб присвоить резльтат переменной с.
Для более простого понимания можно написать так: с=(a=b). Не понимаю почему так, но так. Наверно я что-то паропустил в самом начале.
так потому что есть понятие ассоциативность операторов(из математики). Ассоциативность бывает справа-налево или слева-направо.
Проще наверно не копировать объект в объект, дабы не парится с перегрузкой методов копирования и присваивания. А то сегодня это один объект, завтра другой, а про то что надо внести изменения еще куда-то никто потом и не вспомнит.
спасибо
А почему бы нам не возвращать &*this из перегруженого оператора? Если я правильно понимаю, то this - указатель объекта на самого себя, *this - сам объект, а &*this - ссылка на этот объект.
Я вообще не понимаю зачем там нужна ссылка если мы возвращаем САМ объект *this...
@@aviator1472 Наверное по сути ссылка там и не нужна, но только потому, что этот перегруженный оператор и так принимает объект по ссылке (в его аргументах задано)
А что если мне нужно будет переинициализировать объект "a" второй раз? Сработает конструктор класса и мы получим утечку?
Конструктор срабатывает один раз при создании экземпляра класса. Затем ты можешь присвоить отдельным паблик полям новые значения (тут нет никакого конструктора), ну либо же присвоить новый объект. Как раз для этого мы и перегрузили оператор присваивания.
Здравствуйте!Подскажите,пожалуйста,оператор присваивания и оператор копирующего присваивания это одно и то же?
c.operator=(a.operator=(b));
Вот, наконец понял
Когда для "c" вызывается перегруженный оператор, мы передаём в его аргументы "a", который в свою очередь должен сначала отработать свою перегруженную функцию и вернуть свой результат работы, поэтому он возвращает в "c" - "return *this;"(себя)
Что такое other, после которого ставится точка и пишется что-то ещё? Помогите, пожалуйста!
А почему нельзя просто очистить память в главной функции, перед return 0?
Допустим ты играешь в игру 10 часов подряд, то уже на 30 минуте тебе нужно будет бежать в магазин за дополнительной ОЗУ.
Лол, надеюсь это был рофл такой
Обязательно возвращать именно ссылку?
Я не понимаю когда мы перегружаем классы, то вводя параметры 10, 2, 5 и т.д они подходят под все перегрузки и по этому всё выводится на экран? А a = b и c = a = b это просто примеры как это выглядит?
Было бы уместное перед тем как начинать удалять массив проверять что other!= this
да если a = a;