Г. Шилдт - Полный справочник по C++ (1109478), страница 61
Текст из файла (страница 61)
Однако, если функция мудиле() перегружена, возникает вопрос, каким образом компилятор может вычислить ее указатель? Ответ зависит от того. как объявлен указатель р. Рассмотрим. например, следующую программу. В1пс1ос)е <1овсгеатп> ив(од паюеврасе вес); ьпе юубвпс(ьпе а); зпс иухипс(зпс а, ьпс Ь): хпе иаьп() ( )пс (*Гр) (ьпс а); // Указатель на Функцию зпо 1(1пс) Йр = юутипс; // Указатель на функцию юуйипс(ьпс) соус « хр(о)) теессп 0; (пс иуювпс(1пс а) Глава 14.
Перегрузка фуим(ий, м)иструкторы копирования и аргументы пв умолчанию ЗУ У геецгп а; ) зпс тугцпс(ьпс а, зпс ь) ( гегцгп а*Ьз ) В этой программе существуют два варианта функции пудппсО. Оба возвращаю- целое число, однако первый вариант получает один целочисленный аргумент, а вто рой — два. Переменная вр объявлена в программе как указатель на функцию„возвращающую целое значение и получающую один целочисленный аргумент. Когда указателю др присваивается адрес функции пуяшзс<), компилятор использует эт информацию лля выбора соответствующей версии, а именно: еазяспс(апа а).
Если бы указатель гр был объявлен иначе: з(з )зпг. (*гр)(гпс а, гпе ь)з, то ему был бы присвоен адрес функции пугппс(1пв а, зпе Ь). Как правило, если указателю присваивается адрес перегруженной функции, выбор варианта осуществляется в зависимости от типа указателя. Кроме того, объявление указателя на функцию должно точно соответствовать только одному из вариантов перегруженной функции.
Анахронизм очейоаб В первоначальной версии языка С++ для создания перегруженной функции требовалось ключевое слово оеег1оазт. В настоящее время оно устарело и больше не поддерживается. Действительно, его нет даже в списке ключевых слов языка С++. Однако, поскольку мы допускаем существование старых программ, представляющих как практический, так и исторический интерес, неплохо вспомнить, как применялось КЛЮЧЕВОЕ Слово о тег1оаз). Рассмотрим общую форму такого объявления. $ оиег1оад имя фуикяии; Здесь имя функции задаст псрегружасмую функцию.
Этот оператор должен предшествовать объявлению перегруженной функции. Например, следующий оператор сообщает старым компиляторам, что функция ееее() является перегруженной. И очег1оаз) Еевс," ~ 1 Аргументы Функции по умолчанию В языке С++ аргументам функции можно присваивать значения, заданные по умолчанию, если соответствующий аргумент при вызове функции был пропущен. Значение по умолчанию задается с помощью синтаксической конструкции, которая очень похожа на инициализацию переменной. Например, следующий оператор объявляет, что функция яудспс () получает один аргумент типа <)опЬ1е, по умолчанию принимающий значение О.О. иоЫ взугспе(з)ооЬ1е д = О.О) ( // ) Часть 11. Язык С++ Теперь функцию во/депо () можно вызвать двумя способами.
иугцпс(190.234)г // Перелача явного значения иугцпс О г // Функция использует значение ло умолчанию При первом вызове параметр гт получает значение 198.234. Во время второго вызова параметр (( автоматически принимает значение 0.0. Параметры по умолчанию позволяют справляться с возрастающей сложностью программ. Во многих случаях функции содержат больше параметров, чем нужно в конкретной ситуации. Таким образом, в каждом конкретном случае достаточно указать лишь необходимые параметры, а не все сразу. Например, многие функции вволавывода используют именно этот механизм. Рассмотрим простую программу, иллюстрирующую применение параметров функции по умолчанию.
Функция с1гвсг(] очишает экран дисплея, стирая все строки (кстати, это не самый эффективный способ). Поскольку, как правило„в текстовом режиме на экране дисплея помещаются 25 строк, параметр функции по умолчанию принимает значение 25. Однако в некоторых случаях на экран может выводиться разное количество строк, как больше, так и меньше 25. Поэтому параметр по умолчанию можно заменить явным значением.
Втпс1цг]е <1овсгеа~п> цвьпо паюеврасе вериг чоЫ с1гвсг(1пс айве=25); 1пс пайп(1 гед1всег Ыс 1; Гог(1=Ог 1<30г 1++ ) сопл « 1 « епг]1; с1п.пес()г с1гвсг(); // Стирает 25 строк гог(1=0] 1<30г 1++ ) соцс « 1 « епг]1; стп.оее()г с1гвсг(10); // Стирает 10 строк гесцгп 0; ) чоЫ с1гвсг(Ыс эйве] ( гог(] в1вег вьге †) соцс « епг)1г ) Этот пример иллюстрирует ситуацию, в которой достаточно параметра по умолчанию. В этом случае функция с1гвог() вызывается без параметров.
Однако при необходимости значение по умолчанию можно заменить и с помощью переменной в1ве явно задать другое значение. Аргумент по умолчанию можно применять в качестве признака, сообщающего функции, что ей необходимо использовать предыдущее значение аргумента. Проиллюстрируем зту ситуацию с помощью функции 1реев(1, предназначенной дчя автоматической вставки перед строкой заданного количества пробелов.
Для начала рассмотрим версию атой функции, в которой не предусмотрен аргумент по умолчанию. | чоЫ ьрцсв(спал *всг, Ыс 1пг]епс) ( Н(1пг]епс < 0) 1пцепс = 0; Глава 14. Перегрузка функций, конструкторы копирование и аргументы по умолчанию 318 бою( ; ьпйепс; 1пйепс--) соис « соис « всю « "М"; Эта версия функции ариев() вызывается с двумя аргументами: строкой и количеством пробелов перед ней.
Однако функцию 1приев() можно усовершенствовать, предусмотрев лля аргумента йпйепе значение по умолчанию. Очень часто на экран выводятся строки, имеюшие определенный отступ от края экрана. В этой ситуации можно не повторять аргумент хпйепс постоянно, а просто задать его значение по умолчанию н вызвать функцию арисв() С одним параметром всю. Этот подход иллюстрируется слсдуюшей программой. айпс)ийе <йовсдеат> ив1пд пащеврасе вой; /* Гю умолчанию параметр тпйепс равен -1.
Это значение заставляет функцию использовать предыдущую величину отступа. */ чо1й йрш.э(сиад *вел, ьпс йпйепе = -1); йпс ща1п() ( зри\ в ( "Общий привет", 10!; ьригв("Перед этой строкой вставлены 10 пробелов"); ариев("Перед этой строкой вставлены 5 пробелов", 5) ьрися("Перед этой строкой нет пробелов", О); десихп 0; чойй ариев(спад *всю, ьпе юпйепс) ( всасйс 1 =. 0; // Применяется предыдущее значение параметра 1пйепс 1г(1пйепс >= О) 1 = )пс)епс; е1ве // Используется старое значение параметра впйепс ьпйепе год( ; (пйепе; 1пйепе--! соис « соис «вес « "1п"; ) Эта программа выводит на экран следующие строки.
1 Всем привет Перед этой строкой вставлены 10 пробелов Перед этой строкой вставлены 5 пробелов Перед этой строкой нет пробелов Созлавая функции с аргументами по умолчанию, важно гюмнитгь что их значения можно задать лишь один раз во время объявления функции. В предыдущем примере значение по умолчанию было указано в прототипе функции ариев(). Если попытаться задать новое (или даже то же самое значение) в определении функции 3риев(), компилятор выдаст сообшение об ошибке.
Хотя значения аргументов по умолчанию Часть й. Язык С++ переопределить невозможно, можно задавать разные значения для каждой версии перегруженной функции. Все параметры, принимающие значения по умолчанию, должны располагаться правее обычных аргументов. Например, следующее определение функции ариев() является неправильным. * 1/ Оиибха! иоьп ьригв(ьпс 1пцепс = -1. сьат *ест) Начав определять параметры, принимающие значения по умолчанию, нельзя перемежать их обычными параметрами. Иначе говоря, следующее объявление является неверным. и 1пс тутипс(г1оас т, сиат *ест, 1пс 1=10, ьпе б); Поскольку значение параметра 1 задается по умолчанию, параметр з также должен иметь значение по умолчанию. Параметры конструктора тоже могут иметь значения по умолчанию Например, в классе сиЬе задаются целочисленные размеры куба.
Если конструктор вызывается без параметров, размеры куба по умолчанию равны нулю. Мьпс1иде <Ьовстеаж> ив1ид иатеврасе вес); с1авв сиЬе ( 1пс х, у, аг риЬ11с: сиЬе(1пс 1=0, хпс 0=0, зпс К=О) ( х=-1; у=э' а=ум ) ьпс ио1ипе(] ( теситп х*у"а; 1пс ма1п() ( сиЬе а(2,3,4), Ь; ссис «а.иошпе() «епд1г соис « Ь.ио1иве(); теситп 0; ) Параметры конструктора, заданные по умолчанию. предоставляют два преимущества. Во-первых, они позволяют избежать применения перегруженного конструктора без параметров.
Например, если бы параметры конструктора сиЬе() не были заданы по умолчанию, для обьявления объекта Ь понадобился бы второй конструктор: и сиЬе() (х=О; у=О; а=О) Во-вторых, задать самые распространенные значения аргуме~пов по умолчанию удобнее, чем повторять их постоянно. Глава )4. Перегрузка Функций, конструки)ры копирования и аргумвитм по уиовчвиив ЭИ Аргументы по умолчанию и перегрузка В некоторых ситуациях аргументы по умолчанию оказываются сокращенной формои перегрузки. Примером этой ситуации является класс сц)за. Теперь рассмотрим сше один, Допустим, необходимо создать две настраиваемые версии стандартной функции ветсас().
Первая версия булет практически совпадать с функцией ветсас() и конкатенировать целыс строки. Вторая версия предусматривает третий параметр, задающий количесгво конкатснируемых символов. Иначе говоря, вторая версия этой функции приписывает к первой строке лишь заданное количество символов из второй строки. Итак, функция муветсае () будет иметь следующие прототипы, чо10 ыувстсас(спет *в1, сЬат *в2, .лс 1ег.); чо10 тувстсас(снят *в1, сЬат в2); Первая версия функции туветсае<) дописывает 1еп символов строки вз в конЕц строки в1.
Вторая версия дописывает в конец строки в1 всю строку вз. Разумеется, можно было бы реализовать обе версии функции тувстсае(), однако есть более простой способ. Используя аргумент по умолчанию, можно создать лишь одну версию функции вуветсае() для обоих вариантов. Этот способ продемонстрирован с помощью следующей программы. // Настраиваемая версия Функции встсас(] $1лс1цое <1овттеаи> Вьпс1цг]е ссвттьпя> цвьлд патеврасе всо; чоьг) иувстсас(сйат *в1, айат *в2, 1лс 1еп = -1); ьпс каьлИ ( спал ятт1[80) = "Проверка"; сиат вст2[80) = "0123458289"р иувттсат(втт1, втт2, 5); // Конкатенируем 5 символов соцс « вст1 « 1п'; астору(втт1, "проверка"); // Строка вст1 ыувттсас(вст1, вст2); // Конкатенируем целые строки сост « вст1 « ' 1п'; те<цтл 0; ) // Настраиваемая версия Функции вттсат(). чо10 тувстсас(сЬат "в1, сЬат *в2, 1пс 1ел) // Находим конец строки в1 ик11е (*в1) в1++," 11(1ел == -1) 1ел = втт1еп(в2]; ии11е(*в2 аа 1ел] *в1 = *в2; // Копируем символы в1++; в2++; 1еп--] ) 816 Часть П.
Язык С++ Здесь функция шувсхеас[) конкатенирует 1еп символов из строки, на которую ссылается указатель вя, в конец строки, на которую ссылается указатель в1. Однако, если параметр 1вп по умолчанию равен †(, функция юуасхсас() конкатенирует целые строки.(Таким образом, если параметр 1еп равен — 1, функция аувсхсас() работает как сгандартная функция всхеасО.) Используя параметр по умолчанию, можно объединить две версии функции в одной. Иначе говоря, в этом смысле параметры по умолчанию являются альтернативой перегрузке функций.