Когда происходит вызов функции print()
с передачей аргумента типа double()
, процесс повторяется. Компилятор находит локальное определение функции print(int)
. Но аргумент типа double
может быть преобразован в значение типа int
, поэтому вызов корректен.
Если бы объявление print(int)
находилось в той же области видимости, что и объявления других версий функции print()
, это была бы еще одна ее перегруженная версия. В этом случае вызовы распознавались бы по-другому, поскольку компилятор видел бы все три функции:
void print(const string &);
void print(double); //
void print(int); //
void fooBar2(int ival) {
print("Value: "); //
print(ival); //
print(3.14); // вызов
}
6.5. Специальные средства
В этом разделе рассматриваются три связанных с функциями средства, которые полезны во многих, но не во всех программах: аргументы по умолчанию, встраиваемые функции и функции constexpr
, а также некоторые другие средства, обычно используемые во время отладки.
6.5.1. Аргументы по умолчанию
Параметры некоторых функций могут обладать конкретными значениями, используемыми в большинстве, но не во всех вызовах. Такие обычно используемые значения называют
Например, для представления содержимого окна можно было бы использовать тип string
. Мы могли бы хотеть, чтобы по умолчанию у окна была определенная высота, ширина и фоновый символ. Но мы могли бы также захотеть позволить пользователям использовать собственные значения, кроме значений по умолчанию. Чтобы приспособить и значение по умолчанию, и определяемое пользователем, мы объявили бы функцию, представляющую окно, следующим образом:
typedef string::size_type sz; // typedef см. p. 2.5.1
string screen(sz ht = 24, sz wid = 80, char backgrnd = ' ');
Здесь мы предоставили для каждого параметра значение по умолчанию. Аргумент по умолчанию определяется как инициализатор параметра в списке параметров. Значения по умолчанию можно определить как для одного, так и для нескольких параметров. Но если у параметра есть аргумент по умолчанию, то все параметры, следующие за ним, также должны иметь аргументы по умолчанию.
Если необходимо использовать аргумент по умолчанию, его значение при вызове функции пропускают. Поскольку функция screen()
предоставляет значения по умолчанию для всех параметров, мы можем вызвать ее без аргументов, с одним, двумя или тремя аргументами:
string window;
window = screen(); //
window = screen(66); //
window = screen(66, 256); //
window = screen(66, 256, '#'); //
Аргументы в вызове распознаются по позиции. Значения по умолчанию используются для аргументов, крайних справа. Например, чтобы переопределить значение по умолчанию параметра background
, следует поставить также аргументы для параметров height
и width
:
window = screen(, , '?'); //
// крайние справа
window = screen('?'); //
Обратите внимание, что второй вызов, передающий одно символьное значение, вполне допустим. Несмотря на допустимость, это вряд ли то, что ожидалось. Вызов допустим потому, что символ '?'
имеет тип char
, а он может быть преобразован в тип крайнего левого параметра. Это параметр типа string::size_type
, который является целочисленным беззнаковым типом. В этом вызове аргумент типа char
неявно преобразуется в тип string::size_type
и передается как аргумент параметру height
. На машине авторов символ '?'
имеет шестнадцатеричное значение 0x3F
, соответствующее десятичному 63
. Таким образом, этот вызов присваивает параметру height
значение 63
.