Например, гипотетически вы инженер-программист, а не инженер-электронщик. На уровне 1, физическом уровне, вы чувствовали бы себя очень некомфортно, и вам было бы гораздо удобнее работать на уровне 7, прикладном уровне. Возможно, вы слышали термин «full-stack-инженер». Такой инженер способен продуктивно работать на всех уровнях. Но это мифическое создание вряд ли встречается в реальности.
Также подумайте, что случится, если перегруженная версия функции, принимающая логическое значение, будет добавлена после определения конструктора, принимающего std::string const&.
Продвижение означает расширение представления типа. Например, объект типа short может быть продвинут до объекта типа int (такое преобразование называется целочисленным продвижением), а объект типа float может быть продвинут до объекта типа double, что известно как продвижение с плавающей точкой.
Преобразования отличаются от продвижения возможностью изменения значения, что может отрицательно сказаться на точности. Например, значение с плавающей точкой можно преобразовать в целое число, округлив до ближайшего целого. Кроме того, целочисленные значения и значения с плавающей точкой, перечисления без указания области видимости, указатели и типы указателей на члены могут быть преобразованы в логическое значение. Эти три ранга являются концепциями, унаследованными от языка C, и от них невозможно отказаться из-за необходимости поддерживать совместимость с C.
Это частично охватывает стандартные последовательности преобразований. Преобразования, определяемые пользователем, выполняются двумя способами: либо с помощью неявного конструктора, либо с помощью неявного оператора преобразования. Именно этот тип преобразований мы ожидаем в нашем примере: наш аргумент char const* преобразуется в std::string через неявный конструктор, который принимает char const*. Это так же очевидно, как нос на вашем лице. Но с какой целью мы втянули вас в это обсуждение особенностей разрешения перегрузок?
Стандартная последовательность имеет три ранга: точное соответствие, продвижение и преобразование. Точное соответствие означает отсутствие необходимости преобразования и является предпочтительным рангом. Это также может означать преобразование левостороннего (lvalue) аргумента в правосторонний (rvalue).
Сначала он отбирает функции с тем же количеством параметров, с меньшим количеством и с параметром-многоточием или с большим количеством параметров, среди которых избыточные параметры имеют аргументы по умолчанию. Если какой-либо из кандидатов имеет предложение requires (requires clause, нововведение, появившееся в C++20), то оно должно быть удовлетворено. Ни один правосторонний (rvalue) аргумент не должен соответствовать неконстантному левостороннему (lvalue) параметру, и любой левосторонний (lvalue) аргумент не должен соответствовать ссылочному правостороннему (rvalue) параметру. Каждый аргумент должен иметь возможность быть преобразованным в соответствующий параметр посредством неявной последовательности преобразований.
Когда компилятор встречает вызов функции, он должен определить, на какую из функций этот вызов ссылается. Перед этим компилятор составляет список всех идентификаторов. Возможно, что в программе имеется несколько функций с одинаковыми именами, но с разными параметрами — набор перегруженных версий. Как компилятор определяет, какую из них вызывать?
огда компилятор встречает вызов функции, он должен определить, на какую из функций этот вызов ссылается. Перед этим компилятор составляет список всех идентификаторов. Возможно, что в программе имеется несколько функц
В случае с классами высокая связность подразумевает тесную связь функций-членов и данных. Связность увеличивается, когда функции-члены выполняют небольшое количество связанных действий с небольшим набором данных. Высокая связность и слабая сопряженность часто идут рука об руку. Более полную информацию по этой теме можно получить в книге Structured Design37, изданной более 40 лет тому назад, но продолжающей оставаться актуальной и по сей день.