Conversation
| Аналогично, *вниз по иерархии* (от базового к наследуемому) можно кастовать только тогда, когда совпадает динамический тип. Иначе UB. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. | ||
| - `const_cast`. Снимает модификаторы `const` и `volatile`. Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB, так как с помощью `reintepret_cast` очень просто нарушить `strict aliasing rule`. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. Но как правило `reintepret_cast<T2*>(T1*)` работает как `static_cast<T2*>(static_cast<void*>(T1*))`. |
There was a problem hiding this comment.
вообще-то reinterpret_cast из указателя в указатель именно так и определён в стандарте, не надо обращаться ни к каким поставщикам компиляторов (implementation-defined другие версии reinterpret_cast'а, которые здесь не упомянуты, например из указателя в число)
| Аналогично, *вниз по иерархии* (от базового к наследуемому) можно кастовать только тогда, когда совпадает динамический тип. Иначе UB. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. | ||
| - `const_cast`. Снимает модификаторы `const` и `volatile`. Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB, так как с помощью `reintepret_cast` очень просто нарушить `strict aliasing rule`. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. Но как правило `reintepret_cast<T2*>(T1*)` работает как `static_cast<T2*>(static_cast<void*>(T1*))`. |
There was a problem hiding this comment.
почему strict aliasing rule отформатирован как код?
| Аналогично, *вниз по иерархии* (от базового к наследуемому) можно кастовать только тогда, когда совпадает динамический тип. Иначе UB. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. | ||
| - `const_cast`. Снимает модификаторы `const` и `volatile`. Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB, так как с помощью `reintepret_cast` очень просто нарушить `strict aliasing rule`. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. Но как правило `reintepret_cast<T2*>(T1*)` работает как `static_cast<T2*>(static_cast<void*>(T1*))`. |
There was a problem hiding this comment.
после "Но как правило" должна быть запятая (если это выражение останется после изменений)
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. | ||
| - `const_cast`. Снимает модификаторы `const` и `volatile`. Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. | ||
| - `reinterpret_cast` — всё зашкварное из C-style cast'а. Перевод указателей несвязанных друг с другом типов, указателей в число и обратно. Простой и эффективный способ получить UB, так как с помощью `reintepret_cast` очень просто нарушить `strict aliasing rule`. В стандарте так и написано, это implementation-defined cast. Обратитесь к поставщику вашего компилятора, чтобы понять, как у вас работает `reinterpret_cast`. Но как правило `reintepret_cast<T2*>(T1*)` работает как `static_cast<T2*>(static_cast<void*>(T1*))`. | ||
| - `const_cast`. Снимает модификаторы `const` и `volatile` (с помощью `const_cast` можно также навешивать `const`, но это не имеет особого смысла). Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. |
There was a problem hiding this comment.
дописанное в скобках относится не только к const, не вижу смысла уточнять
| - `const_cast`. Снимает модификаторы `const` и `volatile` (с помощью `const_cast` можно также навешивать `const`, но это не имеет особого смысла). Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. | |
| - `const_cast`. Снимает модификаторы `const` и `volatile` (может и навешивать их, но это не имеет особого смысла). Чаще всего это делать не надо, но иногда бывает нужно всё-таки. В стародавние времена, когда `const`'ов не было, были функции, принимавшие указатель. Неконстантный, хотя не меняли его содержимое. И вот если вы хотите использовать эту функцию, вы можете снять `const` с указателя. А вообще правило вот какое: **если изначальный объект был `const`, снимать с него `const` ни в коем случае нельзя (UB). Если изначальный объект константным не был, а потом вы сначала навесили `const`, а потом сняли, то всё хорошо**. |
| ### `protected`. | ||
| Представим, что мы пишем виджет на основе QT. Там есть базовый виджет, у которого есть операции, что делать в случае нажатия мышки, в случае перемещения колёсика и прочее подобное. Вам всё это нужно переопределить. В таком случае в базовом виджете используется ключевое слово `protected`. Оно для похожих случаев и было создано, лол. Это модификатор доступа, дающий доступ только дочерним классам и себе. | ||
|
|
||
| Стоит отметить, что `protected` предоставляет доступ только внутри дочернего класса, то есть если есть функция в `derived` классе и мы передаем в нее объект типа `base`, то обратиться к `protected` полям и функциям `base` мы все равно не сможем. |
There was a problem hiding this comment.
я понимаю, что ты хочешь донести, но сформулировано непонятно, что значит "внутри"? вопрос актуален даже если забить на то, что у derived тоже могут быть наследники, а если не забивать, стоит сформулировать ещё точнее
| Стоит отметить, что `protected` предоставляет доступ только внутри дочернего класса, то есть если есть функция в `derived` классе и мы передаем в нее объект типа `base`, то обратиться к `protected` полям и функциям `base` мы все равно не сможем. | ||
| С ним, правда, есть вопрос. Если метод не ломает инвариант, почему он не `public`, а если ломает, то хотим ли мы давать доступ дочерним классам. Тем не менее, эти вопросы не риторические, если вы нашли на них ответ — делайте `protected`. |
| }; | ||
| ``` | ||
|
|
||
| В данном примере, если в публичном конструкторе будет выброшено исключение, то утечек данных не произойдет, так как приватный конструктор уже закончит свое исполнение к моменту выброса исключения и будет вызван деструктор, который высвободит выделенные ресурсы. |
There was a problem hiding this comment.
пропущена запятая:
| В данном примере, если в публичном конструкторе будет выброшено исключение, то утечек данных не произойдет, так как приватный конструктор уже закончит свое исполнение к моменту выброса исключения и будет вызван деструктор, который высвободит выделенные ресурсы. | |
| В данном примере, если в публичном конструкторе будет выброшено исключение, то утечек данных не произойдет, так как приватный конструктор уже закончит свое исполнение к моменту выброса исключения, и будет вызван деструктор, который высвободит выделенные ресурсы. |
| }; | ||
| ``` | ||
|
|
||
| В данном примере, если в публичном конструкторе будет выброшено исключение, то утечек данных не произойдет, так как приватный конструктор уже закончит свое исполнение к моменту выброса исключения и будет вызван деструктор, который высвободит выделенные ресурсы. |
There was a problem hiding this comment.
а где-то написано о том, почему достаточно срабатывания приватного конструктора? если нет, лучше явно написать
No description provided.