В компьютерном программировании , аргумент по умолчанию является аргумент в функцию , что программист не требуется указывать. В большинстве языков программирования функции могут принимать один или несколько аргументов. Обычно каждый аргумент должен быть указан полностью (как в языке программирования C [1] ). Более поздние языки (например, в C ++ ) позволяют программисту указывать аргументы по умолчанию, которые всегда имеют значение, даже если оно не указано при вызове функции.
Аргументы по умолчанию в C ++
Рассмотрим следующее объявление функции:
int MyFunc ( int a , int b , int c = 12 );
Эта функция принимает три аргумента, из которых последний имеет значение по умолчанию - двенадцать. Программист может вызвать эту функцию двумя способами:
int result = MyFunc ( 1 , 2 , 3 ); результат = MyFunc ( 1 , 2 );
В первом случае значение аргумента c указывается как обычно. Во втором случае аргумент опускается, и вместо него будет использоваться значение по умолчанию 12 .
Невозможно узнать, был ли аргумент указан вызывающим абонентом или использовалось значение по умолчанию.
Вышеупомянутый метод особенно полезен, когда нужно установить критерии по умолчанию, чтобы функцию можно было вызывать с параметрами или без них. Учтите следующее:
void PrintGreeting ( std :: ostream & stream = std :: cout ) { // Это выводит сообщение в указанный поток. поток << "привет, мир!" ; }
Вызов функции:
PrintGreeting ();
по умолчанию будет печатать " hello world !" на стандартный вывод std::cout
(обычно на экран). С другой стороны, любой объект типа std::ostream
теперь может быть передан той же функции, и функция будет печатать в заданный поток, а не в стандартный вывод.
PrintGreeting ( std :: cerr );
Поскольку значения аргументов по умолчанию «заполняются» в месте вызова, а не в теле вызываемой функции, виртуальные функции берут свои значения аргументов по умолчанию из статического типа указателя или ссылки, через которую выполняется вызов, а не из динамического типа объекта, поставляющего тело виртуальной функции.
struct Base { виртуальный std :: pair < int , int > Foo ( int x = 1 ) { return { x , 1 }; } };struct Derived : public Base { std :: pair < int , int > Foo ( int x = 2 ) override { return { x , 2 }; } };int main () { Производный d ; База & b = d ; assert ( d . Foo () == std :: make_pair ( 2 , 2 )); assert ( b . Foo () == std :: make_pair ( 1 , 2 )); }
Перегруженные методы
Некоторые языки, например Java , не имеют аргументов по умолчанию. Однако такое же поведение можно смоделировать с помощью метода перегрузки , чтобы создать перегруженные методы с тем же именем, которые принимают разное количество аргументов; а версии с меньшим количеством аргументов просто вызывают версии с большим количеством аргументов с аргументами по умолчанию в качестве отсутствующих аргументов:
int MyFunc ( int a , int b ) { return MyFunc ( a , b , 12 ); } int MyFunc ( int a , int b , int c ) { / * здесь основная реализация * / }
Однако в дополнение к нескольким другим недостаткам , поскольку аргументы по умолчанию не моделируются в системе типов, тип обратного вызова (он же функция высшего порядка) не может выражать, что он принимает ни одну из перегрузок, ни имитирует аргументы по умолчанию с помощью перегруженные функции. Принимая во внимание, что в JavaScript определение неперегруженной функции может заменить значение по умолчанию, когда входное значение равно undefined
(независимо от того, было ли это неявно undefined
через отсутствие аргумента на сайте вызова или явно переданное undefined
значение); который моделируется как необязательный тип параметра аргумента ?:
в TypeScript . Решение JavaScript не разрешается статически (то есть не во время компиляции, поэтому TypeScript моделирует только опциональность, а не значения по умолчанию в сигнатуре типа функции), таким образом, влечет дополнительные накладные расходы времени выполнения, хотя он обеспечивает большую гибкость в том, что обратные вызовы могут независимо контролировать их значения по умолчанию, а не централизованно диктовать (подпись типа обратного вызова в) подпись типа функции, которая вводит обратный вызов. Решение TypeScript может быть смоделировано в Java с Optional
типом, за исключением того, что аналог неявного undefined
для каждого отсутствующего аргумента является явным Optional.
на месте вызова.
Оценка
Для каждого вызова функции значения аргумента по умолчанию должны быть переданы вызываемой функции.
Если значение аргумента по умолчанию содержит побочные эффекты, это важно, когда эти побочные эффекты оцениваются - один раз для всей программы (во время синтаксического анализа, компиляции или загрузки) или один раз на вызов функции, во время вызова.
Python - известный язык, который оценивает выражения в аргументах по умолчанию один раз во время оценки объявления функции. Если требуется оценка для каждого вызова функции, ее можно реплицировать, указав в качестве аргумента по умолчанию контрольное значение , например None
, и затем заставив тело функции оценивать побочные эффекты значения по умолчанию только в том случае, если контрольное значение было передано.
Например:
случайный импортЗащиту стремится ( = случайными . случайные ()): возвращение x = eager () y = eager () assert x == ydef lazy ( a = None ): если a равно None : a = random . случайным образом () возвращение x = lazy () y = lazy () assert x ! = y
Степень
Как правило, аргумент по умолчанию будет вести себя идентично аргументу, переданному параметром или локальной переменной, объявленной в начале функции, и будет иметь ту же область действия и размер (время жизни), что и параметр или другая локальная переменная, а именно автоматическая переменная, которая освобождается. по завершении функции.
В других случаях вместо этого статически может быть назначен аргумент по умолчанию. Если переменная является изменяемой, она будет сохранять свое значение при вызовах функций, как в случае статической переменной .
Такое поведение встречается в Python для изменяемых типов, таких как списки. Как и в случае с оценкой, чтобы гарантировать ту же степень, что и у локальной переменной, можно использовать контрольное значение:
Защиту нетерпеливый ( а = []): возвращение x = eager () x + = [ 1 ] assert eager () == [ 1 ]def lazy ( a = None ): если a равно None : a = [] вернуть ax = lazy () x + = [ 1 ] assert lazy () == []
Рекомендации
- ^ Лесли, Мартин. «Параметры по умолчанию» . Справочник по программированию на C ++ . Архивировано из оригинала 9 октября 2011 года . Проверено 13 января 2012 года . CS1 maint: обескураженный параметр ( ссылка )