LINUX.ORG.RU

C++ непонимание наследования классов

 


0

4

Здравствуйте, коллеги!

class Parent{
private:
  int i;
public:
  Parent& operator = (Parent &p){
    this->i = p.i;
  }
};

class Child: public Parent{

};

Мне нужно сделать конструкцию типа:

Parent p;
Child c;
c = p;

Т.е. что бы, по большому счету сработал перегруженный оператор «=» из родительского класса. Произошла инициализация "i"б находящийся в protected базового класса. Но я не понимаю как это сделать.



Последнее исправление: HighMan (всего исправлений: 2)

Ответ на: комментарий от AntonI

ЕМНИП для каких то простых юзеровских POD типов значение предпочтительнее?

Тут мы углубляемся в ABI, но в случае inline compiler сделает правильную вещь. А так да - integers лучше таскать по значению, а arg int-by-ref is a crime, IMHO, особенно в 64 битах.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

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

С ходу ничего противоречащего этому я придумать не могу (разве что возню с указателями).

Так что согласен, видимо ссылки на this или на поля класса из методов можно возвращать не опасаясь.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от AntonI

Есть для POD какая то общая рекомендация, типа размеры до 128 бит по значению, если больше то по ссылке?

Я тебе потом интересный видосик скину - да, даже «тяжелые» аргументы если по значению позволяют очень интересные вещи проворачивать… Но что касается accessors - только по ссылкам. Да.

bugfixer ★★★★★
()
Ответ на: комментарий от Ivan_qrt

ссылки на this или на поля класса из методов можно возвращать не опасаясь.

Я могу придумать кучу вариантов когда так делать нельзя. Это же плюсы, тут когда кодишь нужна осознанность…

AntonI ★★★★
()
Ответ на: комментарий от Ivan_qrt

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

Однозначно нет. Это слишком сильное утверждение.

bugfixer ★★★★★
()
Ответ на: комментарий от AntonI

Ну у меня не получилось ничего вменяемого. Так чтобы с возвращением копии было всё ок, а с возвращением ссылки не ок. Ну и естественно без предупреждений со стороны компилятора. Игнорируешь предупреждения где не надо - сам виноват.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от Ivan_qrt

Так чтобы с возвращением копии было всё ок, а с возвращением ссылки не ок.

На самом деле всё тривиально. Достаточно иметь что-то в духе

const string& foo(const string&)

И подсунуть туда C-string.

Но вопрос не об этом… Делать accessors возвращающие что-то отличное от const-ref не имеет смысла делать никогда.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Делать accessors возвращающие что-то отличное от const-ref не имеет смысла делать никогда.

Ну и возвращать не const ref, а просто ref нужно если надо модифицировать значение. operator[] в vector - классический пример.

А возвращать копию для доступа нужно если это какая-то лёгкая копия, типа span или string_view. Оно будет быстрее за счёт меньшей косвенности.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от Ivan_qrt

Это не метод класса возвращающий ссылку на *this.

Однозначно. Но не поверите - довольно распространённая ошибка. А с возвратом чего угодно из класса который outlive вызов - с этим не будет проблем никогда…

bugfixer ★★★★★
()
Ответ на: комментарий от AntonI

Мда. Пути компилятора неисповедимы. Он в более сложных случаях выдаёт предупреждения о провисших ссылках, а тут сломался на ровном месте. Я это даже проверять не стал.

Ну тогда возвращаюсь к исходному утверждению. Если сомневаешься, то возвращать надо копию, а ссылку только если уверен, что при использовании всё будет ок.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от bugfixer

А с возвратом чего угодно из класса который outlive вызов - с этим не будет проблем никогда…

Так outlive надо не вызов. Outlive надо возвращённую ссылку.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от AntonI

Ну это утверждение из разряда сперва изучи все аспекты C++, только потом начинай писать код. Я думаю ты и сам прекрасно понимаешь, что так не бывает.

В процессе изучения писать код надо. В том числе и до того, как разобрался во всяких lvalue, rvalue и временах жизни.

Но даже если со всем этим уже не возникает вопросов, прежде чем возвращать из какой-то функции ссылку нужно задаться вопросом, а насколько это оправдано и можно ли в данном случае так делать.

Собственно это и есть осознанное программирование, просто дефолтом должна быть копия, а возврат ссылки должен быть осознанным решением.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от Ivan_qrt

Нет, все аспекты изучать не обязательно - но что такое ссылки и указатели знать необходимо, это азы.

А в приведённом мной примере надо просто знать (и подумать прежде чем пишешь bar) что делает .foo().

Вы же предлагаете в принципе шарахаться от ссылок - вот этого точно не надо. Особенно с учётом того, что некоторые вещи тупо ломаются при возврате значения вместо ссылки, например перегруженная операция []

AntonI ★★★★
()
Ответ на: комментарий от Ivan_qrt

В процессе изучения писать код надо. В том числе и до того, как разобрался во всяких lvalue, rvalue и временах жизни.

Для пет-проектов без дедлайнов.

На С++ писать код надо осознанно, но это в первую очередь значит, что нужно четко понимать что ты хочешь сделать. А потом уже смотреть какие есть средства языка для этого, имхо, именно это и есть хорошее изучение языка (но после освоения базы – процедурного программирования, указатели, ссылки, основы ООП, стили написания кода, – эту базу все же лучше осваивать под присмотром учителя).

soomrack ★★★★
()
Ответ на: комментарий от AntonI

Нет. Правильное утверждение - кодить на плюсах надо ОСОЗНАННО. Это сложный язык позволяющий очень просто отстрелить себе обе ноги.

Угу. Я все больше согласен с одним влогером, который вещает, что C++ - must die!

По началу, когда я подобное услышал, меня аж перекорежило. Однако, влогер все бытро расставил по местам. С++ - must die. С - live forever.

Тут высказывали предроложение, что я некий студиозус, пишущий лабу…

Не верное предположение.

Я сисадмин с 30 летним стажем :)

Просто я писал на С/С++ очень давно и под Windows. Потом лет 20 прграммированием не занимался, но вот теперь снова понадобилось.

Началось все со скриптов по автоматизации на bash… Быстро пересел на Python, абы логику на bash script реализовывать мучительно.

Ну и… Вспомнилось, что еще я на С что-то умел, да и задачи оказались сильно зависимые от быстродейсвия и потребления ресурсов.

Вот и начал вспоминать С и С++.

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

Копия рожденного объекта сразу запихивается в map, а статический объект разрушается через пару строк кода.

Только поковырявшись с этим делом я понял, что вся эта статика и тяжелое наследование лишь мешают. Куда проще, понятнее и эффективнеее, рождать объекты через new и не заниматься копированием объектов, а укзателей на них.

HighMan
() автор топика
Ответ на: комментарий от HighMan

С++ - must die. С - live forever.

Проще и правильнее закопать этого влогера. Ну или отобрать у него камеру, нефиг транслировать всякую хню в широкие массы.

С++ для некоторых задач безальтернативен. Заявления что что то там маст дай делаются как правило неумными людьми с ограниченным кругозором. Тебе не нравятся плюсы/питон/латынь/вышивание крестиком? Ты это не асилил? Сиди на попе ровно и не трынди о том в чем не разбираешься.

Куда проще, понятнее и эффективнеее, рождать объекты через new

Удачи с поисками new в С. Если в плюсах (питоне/латыни/вышивания крестиком) что то кажется ненужным- значит у Вас пока не было задач где это нужно. Просто не используйте это, никто не заставляет.

AntonI ★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от HighMan

Welcome back on board!

Большинство из нас такие. Количество людей старше 35, имевших хорошие курсы по программированию в российских ВУЗах исчезающе мало. Я почти все время в своей жизни что-то кодил, всякие пет проекты, что-то приносило денег как проекты, что-то под заказ, на разных языках (но это не было моей основной деятельностью никогда). Но лет 12 назад я вдруг понял, что пишу код как мудак, потому что мой код такой, как его писали 30+ лет назад. У меня ушел год на то, чтобы перестроиться и как-то начать писать код в современном стиле, т.е. с использованием конвенций оформления кода, с новыми возможностями языков (тут всякие книги best practice помогли и заглядывание в стандарты, т.к. там часто пишут для чего новые фичи вводят) и пр.

Если ты хочешь писать код на С++, то тебе стоит осознать, что это не С, это другая идеалогия. Эти языки имеют сходный синтаксис, но принцип написания программ у них сильно разный.

Ну и да, не надо использовать наследование и ООП там, где оно не отвечает решаемой цели. Это один из инструментов упрощения кода, но не единственный.

А если хочешь получить совет по своему коду на С++, то лучше вместе с кодом четко формулировать задачу, которую решаешь, т.к. хороший код должен решить именно ее.

soomrack ★★★★
()
Ответ на: комментарий от AntonI

Вы же предлагаете в принципе шарахаться от ссылок

Я не предлагаю отказываться от ссылок. У нас разногласия только в том, что делать, когда до конца не понятно что делать.

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

что некоторые вещи тупо ломаются при возврате значения вместо ссылки

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

Но речь-то не про то, что всегда нужно возвращать копию. Речь про то, что возврат ссылки плохой дефолт.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от soomrack

А если хочешь получить совет по своему коду на С++, то лучше вместе с кодом четко формулировать задачу, которую решаешь, т.к. хороший код должен решить именно ее.

Конечно. Четко сфрмулированная задача - 90% вероятности получения правильного ответа. Кто бы спорил!

Другое дело, что не всегда даже сформулировать четко задачу не получается. А если и получается, то требует очень много слов.

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

Судя по отзывам уважаемых форумных коллег, моя идея с копированием родительских объектов не самая удачная. Да и ссылки на объекты для пока не совсем ясны.

Возможно, ссылки на объекты и их копирование в чем-то хороши, а может быть более модны, но меня они больше запутывают.

Работа с указателями мне куда более привычна.

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

Кстати! Может ли метод класса суицидничать?

Т.е. может ли метод класса вызвать delete this, если объект был создан динамически?

HighMan
() автор топика
Последнее исправление: HighMan (всего исправлений: 2)
Ответ на: комментарий от HighMan

Другое дело, что не всегда даже сформулировать четко задачу не получается.

Ну если не получается четко, то можно и как получится.

На самом деле я сделал простенький класс-обертку Socket над socket.

Дальше я создаю еще один класс Talk, наследованный от Socket;

Вопрос, зачем? Какую функциональность в класс socket добавит наследник?

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

Может лучше было бы просто сделать поле типа socket в твоем классе/структуре? Это, с учетом того, что ты хочешь получить при перегрузке «=», выглядит логичней.

soomrack ★★★★
()
Ответ на: комментарий от HighMan

Отличие ссылок от указателей - это то, что их нельзя менять и не надо разыменовывать. За исключением пары символов код с ссылками и указателями будет идентичен.

Пока создаётся впечатление, что ты под ссылками подразумеваешь что-то своё.

А в целом по теме - пиши на той части языка, которую хорошо понимаешь и не парься. Разберёшься в других частях - начнёшь использовать и их.

Повозишься с отладкой - наглядно поймёшь почему C++ удобнее C и никакие влоггеры тебя ни в чём не убедят.

Ну и рассуждения экспертов об абстрактных задачах до добра не доводят, да.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от HighMan

Т.е. может ли метод класса вызвать delete this, если объект был создан динамически?

Технически не вижу в этом проблем, т.е. может. Результат (напр. сегфолт) будет зависеть от того, как конкретно это вызвано. Но писать такой код, гм, странно.

soomrack ★★★★
()
Последнее исправление: soomrack (всего исправлений: 1)
Ответ на: комментарий от soomrack

Вопрос, зачем? Какую функциональность в класс socket добавит наследник?

Я сделал обертку классом Socket обычной библитеки socket. Старался сделать этот класс пригодным для разных задач (tcp/udp).

Так как этот класс делался максимально универсальным, то он вышел довольно «низкоуровневым».

Для более удобной работы я создал еще один класс, который будет предоставлять более высокий уровень для конкретной задачи, но базируется он на том же «низкоуровневом» Socket.

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

Совершенно верно.

Может лучше было бы просто сделать поле типа socket в твоем классе/структуре? Это, с учетом того, что ты хочешь получить при перегрузке «=», выглядит логичней.

Не совсем понял предложение.

Не наследовать класс Socket, а просто в новом классе хранить объект (динамический или статический) класса Socket?

HighMan
() автор топика
Ответ на: комментарий от HighMan

Не наследовать класс Socket, а просто в новом классе хранить объект (динамический или статический) класса Socket?

да.

Моя логика тут такая:

  1. ты хочешь работать с сокетами через класс, т.к. тебе так удобнее организовать код, => ок, ты создал класс Socket

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

soomrack ★★★★
()
Последнее исправление: soomrack (всего исправлений: 1)

Поскольку забыл уже С++, а вспоминать надо - жизнь того требует, попробовал разобраться с этим примером, восстанавливая полустертые записи в нейронах мозга. Я написал простенькую программку:

class Parent{

private:

int i;

public:

Parent& operator = (Parent &p){

this->i = p.i;

return *this;

}

};

class Child: public Parent{

};

int main (void)

{

Parent p;

Child c;

(Parent)c = p;

return 0;

};

Сохранил ее в файлике test.cpp и компилировал командой gcc test.cpp -o test Ее тоже пришлось вспоминать из затянувшихся пылью чердаков мозга.

Так вот, сначала пришлось дополнить описание оператора: return *this; потому что этот оператор по его определению возвращает объект определенного типа. А затем мне еще пришлось вгрубую сделать кастинг: (Parent)c = p; Как он правильно делается, я забыл, но в данном случае подошло. Все потому, что оператор «operator =» связан с конкретным типом Parent, и он ничего не значет про тип Child. Пусть даже структуры этих классов идентичны, формально - это разные типы переменных для комплитора (переменные, или экземпляры p и c). Поэтому - кастинг.

Возможно, если в определении оператора «operator=» использовать шаблон типа (это что-то, использующее <…>, но это я еще хуже помню), то тогда оно сработает и для экземпляра класса Child.

igorbounov
()
Последнее исправление: igorbounov (всего исправлений: 2)
Ответ на: комментарий от Ivan_qrt

Речь про то, что возврат ссылки плохой дефолт.

Речь про то, что дефолта тут НЕТ. Если важна производительность (иначе напуркуа С++? есть другие, более удобные ЯП) то как правило возвращаются ссылки и код пишется исходя из того что возвращаются ссылки.

Если производительность неважна, библиотеки написаны через опу и бояться сегфолтов - ок, возвращаются значения. ИМНО это странный паттерн, но м.б. и такое бывает.

Можно еще делать возврат по ссылке через аргумент, тут и овцы сыты и волки целы. С-стайл и вот это вот все…

Но ни один из этих вариантов не отменяет необходимости думать/следить за тем что именно делается. Все таки плюсы не питон.

AntonI ★★★★
()
Последнее исправление: AntonI (всего исправлений: 2)
Ответ на: комментарий от HighMan

Не наследовать класс Socket, а просто в новом классе хранить объект (динамический или статический) класса Socket?

конечно. читай обширные обсуждения - «композиция против наследования», которые возникли еще на заре ООП.

наследование используется для семантической иерархии классов. композиция используется для реализации классов.

простой пример - автомобиль есть средство передвижения, и хотя и имеет двигатель(колеса, руль), не является двигателем(колесами, рулем). Он даже не является простой суммой двигателя, колес и руля, а сложной их взаимосвязанной композицией.

то есть автомобиль наследует класс «Средство передвижения»(поскольку им является), но аггрегирует и инкапсулирует в себе - двигатель, колеса, руль, не наследуя их.

alysnix ★★★
()
Ответ на: комментарий от soomrack

Но лет 12 назад я вдруг понял, что пишу код как мудак, потому что мой код такой, как его писали 30+ лет назад.

Я могу поинтересоваться - чего такого фундаментального поменялось за последние 30 лет?

bugfixer ★★★★★
()
Ответ на: комментарий от Ivan_qrt

Ты предлагаешь возвращать ссылку в любой непонятной ситуации

Inline accessor в виде возврата ссылки практически бесплатен - это эквивалент утверждения «можно прочитать по offset X в структуре Y». Нужно довольно хорошо понимать что делаешь заводя accessor by-val. Плюс проблемы slicing. Ну, или мы совсем о разных вещах говорим.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Фундаментального в написании кода? С 80-х? Много чего…

  1. Стали гораздо больше внимания уделять стилю кода. Писать лапшу без форматирования и с однобуквенными переменными уже не приемлимо даже для пет-проектов.

  2. Существенно больше внимания стали уделять безопасному коду. Механизм исключений стал де-факто необходимым базовым знанием.

  3. Стали меньше внимания уделять оптимизации в пользу читаемости кода. Компы стали быстрыми и оптимизация теперь нужна только там, где она действительно необходима алгоритмически. Ну и понимания того, что реальный комп сильно отличается от теоретического, стало больше, соотв. это сказалось на оптимизации.

  4. Языки сильно развились, в них появились инструменты для высокоуровневого программирования, больше абстракций стало. Например, в С++ появился STL.

  5. Элементы лямбда-кода сильнее проникает во многие языки. Языки становятся более выразительными.

  6. Сформировалось большое количество устоявшихся концепций, форматов и библиотек, например, json.

PS: тот же Страуструп регулярно говорит (до сих пор), что главная проблема программистов на С++ это то, что они пишут код в стиле 80х, хотя с тех пор очень много чего поменялось и появилось. И это основная причина всяких проблем с «небезопасностью» С++.

soomrack ★★★★
()
Последнее исправление: soomrack (всего исправлений: 1)
Ответ на: комментарий от soomrack

Вот Игорь сверху написал:

Так вот, сначала пришлось дополнить описание оператора: return *this; потому что этот оператор по его определению возвращает объект определенного типа.

Это у него в Fedore38 gcc так отругался, gcc-13. У меня в el7 поэтому вопросу тишина, типа все ок, gcc-4.8.5

mx__ ★★★★★
()
Ответ на: комментарий от soomrack

Re (1): оно и 30 лет назад так было, мне кажется это Ваше личное восприятие.

Re (3): задачи разные бывают, я и сейчас за лишний malloc() пистончик вставляю.

Re (4): STL это C++98, но согласен - мне нужно было спрашивать про последние 20 лет.

Re (5): лямбды и выразительность для меня несовместимые понятия. По крайней мере плюсовый синтаксис простым смертным (включая меня) воспринимать очень непросто.

Re (6): в целом согласен, но кмк пример с JSON довольно неудачен - я его как «великое достижение» так точно не считаю.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Re (1): оно и 30 лет назад так было, мне кажется это Ваше личное восприятие.

Не было. Достаточно взять практически любую книгу 80х и 90х, там будет адЪ. Даже если взять многотомник Кнута, его код с т.з. оформления выглядит неприемлимо сегодня. Понятно, что сегодняшняя культура возникла не на пустом месте, но массовым это все не было. Одна из причин взлета питона как раз была в том, что там принудительно сделали форматирование кода.

Re (5): лямбды и выразительность для меня несовместимые понятия.

Смотря как писать, конструкция «map(lambda item: item[] expression, iterable)» (пример из python) очень удобна. Я про такие вещи говорю, а не про функциональщину на три экрана.

Re (6): в целом согласен, но кмк пример с JSON довольно неудачен - я его как «великое достижение» так точно не считаю.

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

soomrack ★★★★
()
Ответ на: комментарий от HighMan

Т.е. может ли метод класса вызвать delete this, если объект был создан динамически?

Еще как может (обычно сразу после этого идёт return). Трик состоит в том чтобы убедиться что никто не трогает *this при раскручивании стека после.

К ссылкам вернусь, когда стану лучше их понимать.

Проще всего о них думать как об automatically dereferenced immutable pointers (чем они по сути и являются).

bugfixer ★★★★★
()
Ответ на: комментарий от soomrack

Одна из причин взлета питона как раз была в том, что там принудительно сделали форматирование кода.

Извините но это неправда, я тут в курсе в темы (про питон) и как раз его отступы его главный минус. А взлет Питона характеризуется его простотой, и не обязательным ОО. Я много видел программ и проектов на питон и ОО там в еденицах.

Как то пришлось разбирать 8 Django проектов, и только в одном был ОО подход … я аж удивился.

Смотря как писать, конструкция «map(lambda item: item[] expression, iterable)» (пример из python) очень удобна.

В питоне много чего удобно, теже декортаторы и т.д. что тоже дало ему+, но вроде тут обсуждают с++ а не питон.

mx__ ★★★★★
()
Ответ на: комментарий от bugfixer

Т.е. может ли метод класса вызвать delete this, если объект был создан динамически?

Еще как может (обычно сразу после этого идёт return). Трик состоит в том чтобы убедиться что никто не трогает *this при раскручивании стека после.

Оговорюсь - не самая лучшая идея с архитектурной точки зрения, так как привносит зависимость на то где и как именно был создан объект в логику класса. Но иногда - удобно, да.

bugfixer ★★★★★
()
Ответ на: комментарий от mx__

Извините но это неправда, я тут в курсе в темы (про питон) и как раз его отступы его главный минус.

Это для хороших программистов минус, а для руководителей джуниоров и тех, кто кодить только начинает, это плюс. Такой код поддерживать легче. Впрочем это все, имхо, основанное на субъективных наблюдениях. Питон появился в начале 90х, а массовым языком стал только когда веб развился настолько, что php оказался неудобным, а perl сложным для десятков тысяч вебмастеров.

тут обсуждают с++ а не питон.

можно и из с++ пример привести:

std::ranges::sort(mMyClassVector, [](const MyClass &a, const MyClass &b)
{ 
    return a.mProperty < b.mProperty; 
});
soomrack ★★★★
()
Ответ на: комментарий от soomrack

а для руководителей джуниоров и тех, кто кодить только начинает, это плюс. Такой код поддерживать легче.

В условно больших компаниях в том или ином виде есть coding guidelines / standards (и его ввели не вчера). Вопрос форматирования отпадает сам собой.

можно и из с++ пример привести

Скажите честно - Вы действительно думаете что вот это вот проще для восприятия чем cmp operator объявленный внутри класса? И как часто Вам придётся это повторять? На каждом callsite?

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от bugfixer

В условно больших компаниях в том или ином виде есть coding guadelines / standards (и его ввели не вчера). Вопрос форматирования отпадает сам собой.

Большими компаниями жизнь не ограничивается. Ну и кроме того, при выборе языка есть ряд вопросов, на которые нужно ответить: сколько стоит программист, который будет делать очень простые вещи, сколько программистов можно найти сейчас на рынке, сколько стоит внести изменение в код написанный сегодня через год, и т.п. И внезапно окажется, что если нанять человека, который на питоне делает простую генерацию страниц, то его код поддерживать будет такой же дешевый программист и без всяких стандартов оформления, т.к. форматирование прибито гвоздями и оно у всех одинаково.

Скажите честно …

Согласен, с сортировкой пример плохой, вот лучше:

    std::vector<int> values { 1, 2, 1, 1, 5, 5, 7, 2, 9 };
    const auto success = std::count_if(values.begin(), values.end(), 
                            [](int val) { return val > 2 && val < 6; });
soomrack ★★★★
()
Ответ на: комментарий от soomrack

Согласен, с сортировкой пример плохой, вот лучше

Он «вынужденно лучше» потому как здесь built-ins а не user-defined types. Если бы лично я это писал это был бы «InTheRange» named functor. Reusable, спешу заметить.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Вынуждено, не вынуждено, но мне этот пример нравится своей краткостью и const на результате. Именно этим маленькие лямбда выражения сильны, имхо, – они повышают выразительность кода в простых случаях (например, когда нет своих классов).

Но, конечно, подобные примеры это, по сути, те же циклы.

soomrack ★★★★
()
Ответ на: комментарий от soomrack

Ну и кроме того, при выборе языка есть ряд вопросов, на которые нужно ответить

В рассуждениях которые идут опосля есть одна большая дыра - нет у Вас выбора языка при найме человека в существующий проект.

мне этот пример нравится своей краткостью и const на результате.

Btw, поясните - при чём здесь const?

Именно этим маленькие лямбда выражения сильны

В упор не вижу связи.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от bugfixer

… нет у Вас выбора языка при найме человека в существующий проект.

С этим никто и не спорит, но веб это обычно новые простые проекты, в которых важна скорость первой версии и не очень важно качество кода. И через веб питон и стал массовым.

Мне нравится эта запись

const auto success = std::count_if(values.begin(), values.end(), 
                            [](int val) { return val > 2 && val < 6; });

поскольку:

  1. она не плодит сущностей: переменная в которой хранится результат получает его сразу при объявлении, это к тому же позволяет объявить ее с модификатором const.

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

  3. цикл превратился в одну-две строчки, которые, ко всему прочему, стали еще и единым выражением, его не разделить на части, это просто вызов функции с параметрами. Тем самым, во-первых, код стал более выразителен, с т.з. восприятия это теперь одна команда, а во-вторых, в нем теперь сложнее допустить ошибку/опечатку, которая проскочит через компилятор.

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

soomrack ★★★★
()
Ответ на: комментарий от soomrack

Мне нравится эта запись

const auto success =

Это идиоматически неправильно и не модно нынче. Не хотите Вы «const auto». В частности это отменяет move который был бы возможен без «const».

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Почему?

Я хочу записать полученное значение в переменную и так, чтобы эта переменная не менялась в коде. Можно написать и «const int», зависит от того, что действительно нужно.

soomrack ★★★★
()