Обычный подход является к верхнему регистру строками или нижним регистром их для поисков и сравнений. Например:
>>> "hello".upper() == "HELLO".upper()
True
>>>
Чтобы упростить определение языка и сохранить читабельность кода.
void foo(int x = 2, int y);
Чтобы вызвать это и воспользоваться значением по умолчанию, вам понадобится синтаксис вроде этого:
foo(, 3);
Который, вероятно, считался быть слишком странным. Другой альтернативой является указание имен в списке аргументов:
foo(y : 3);
Необходимо будет использовать новый символ, потому что это уже что-то означает:
foo(y = 3); // assign 3 to y and then pass y to foo.
Подход к именованию был рассмотрен и отклонен комитетом ISO, потому что им было неудобно вводить новое значение к именам параметров вне определения функции.
Если вас интересуют другие обоснования дизайна C ++, прочитайте The Design and Evolution of C ++ by Stroustrup.
Если вы определите следующую функцию:
void foo( int a, int b = 0, int c );
Как бы вы вызывали функцию и указывали значение для a и c, но оставить b по умолчанию?
foo( 10, ??, 5 );
В отличие от некоторых других языков (например, Python), аргументы функции в C / C ++ не могут быть уточнены по имени, как показано ниже:
foo( a = 10, c = 5 );
Если это было возможно, то значение по умолчанию аргументы могут быть где угодно в списке.
Представьте, что у вас есть функция с этим прототипом:
void testFunction(bool a = false, bool b = true, bool c);
Теперь предположим, что я вызвал функцию следующим образом:
testFunction(true, false);
Как компилятор должен выяснить, для каких параметров я хотел задать значения?
Как указывается в большинстве ответов, наличие параметров по умолчанию потенциально в любом месте списка параметров увеличивает сложность и неоднозначность вызовов функций (как для компилятора, так и, вероятно, что более важно для пользователей функции).
В C ++ приятно то, что часто есть способ делать то, что вы хотите (даже если это не всегда хорошая идея). Если вы хотите иметь аргументы по умолчанию для различных позиций параметров, вы почти наверняка можете сделать это, написав перегрузки, которые просто поворачиваются и вызывают встроенную полностью параметризованную функцию:
int foo( int x, int y);
int foo( int y) {
return foo( 0, y);
}
И у вас есть эквивалент:
int foo( int x = 0, int y);
Как правило, параметры функции обрабатываются компилятором и помещаются в стек в порядке справа налево. Поэтому имеет смысл сначала оценить любые параметры со значениями по умолчанию.
(Это применимо к __cdecl, который, как правило, является значением по умолчанию для объявлений функций VC ++ и __stdcall).
Это потому, что он использует относительное положение аргументов, чтобы найти, каким параметрам они соответствуют.
Он мог использовать типы, чтобы определить, что необязательный параметр не был задан. Но неявное преобразование могло этому помешать. Другой проблемой могут быть ошибки программирования, которые можно интерпретировать как выпадение необязательных аргументов вместо ошибки пропущенного аргумента.
Чтобы любой аргумент стал необязательным, должен быть способ идентифицировать аргументы, чтобы убедиться в отсутствии программирования ошибка или устранить двусмысленность. Это возможно в некоторых языках, но не в C ++.
Еще одна вещь, которую комитет по стандартам должен был рассмотреть, - это то, как параметры по умолчанию взаимодействуют с другими функциями, такими как перегруженные функции, разрешение шаблона и поиск имени. Эти функции взаимодействуют очень сложным образом, и их уже трудно описать. Если параметры по умолчанию могут отображаться где угодно, это только усложнит задачу.