Г. Шилтд - Самоучитель C++ (DJVU) (1114955), страница 60
Текст из файла (страница 60)
Пространства имен и другие темы 405 Здесь у конструктора класса п)ус1аяа имеется один параметр. Обратите особое внимание на то, как в функции п1а1пО объявлен объект оЬ. Значение 4, заданное в скобках сразу за объектом оЬ, — это аргумент, который передается параметру х конструктора аус1аяяо и с помощью которого инициализируется переменная а. Именно такая форма инициализации использовалась в примерах программ, начиная с первых глав этой книги. Однако это не единственный способ инициализации. Рассмотрим, к примеру, следующую инструкцию: юус1аяя оЬ = 4; // эта инструкция автонатинески гцоеобраяуется в инструкцию тус1аяя оЬ(4) ) Как показано в комментариях, эта форма инициализации автоматически преобразуется в вызов конструктора шус1аххО со значением 4 в качестве ар- гумента.
Таким образом, предыдущая инструкция обрабатывается компиля- тором так, как будто на ее месте находится инструкция: тпус1а я я оЬ ( 4 ) ) ()1пс1пс(е <ъовткеа)в> цятпд паюеярасе япб; с1аяя юус1аяя ( 1пп а; рцЬ11с; ехр11стп тус1аяя (тпб х) 1пс Чеба() ( пебппп а; ( а=к,' Для такого класса допустима только одна форма конструкторов: птус1аяя оЬ(4) 1 Как правило, всегда, когда у конструктора имеется только один аргумент, можно использовать любую из представленных выше двух форм инициализации объекта. Смысл второй формы инициализации в том, что для конструктора с одним аргументом она позволяет организовать неявное преобразование типа этого аргумента в тип класса, к которому относится конструктор.
Неявное преобразование можно запретить с помощью спецификатора ехрйсй (явный). Спецификатор ехрйсй применим только к конструкторам. Для конструкторов, заданных со специ фикатором ехрйс11, допустим только обычный синтаксис. Автоматического преобразования для таких конструкторов не выполняется. Например, если в предыдущем примере конструктор класса п)ус1ая объявить со спецификатором ехрйсИ, то для такого конструктора автоматического преобразования поддерживаться не будет. В представленном ниже классе конструктор п(ус!авэо объявлен со спецификатором ехрйсй.
406 Само чигель С++ 1. В классе может быть более одного преобразующего конструктора. Например, рассмотрим следующую версию класса юуе)ам, ()1пс1ьк(е <1овскеав> ()1пс1пс(е <свТЖ1Ь> азгпу пашеярасе вСс(; с1аяя твус1аяя ( твом а; риЫ1с: п~ус1авв (1псх) ( а = х; юпус1авв (сЬав *ввк) ( а = а~о1(ввк) г ) гпс де1а() ( теспвп а; тп(.
пигп() преобразование в вызов конструктора тус1аяя оЬ(4) тпус1аяя оЫ =- 4; уу преобразование в вызов конструктора пус1аяя оЬ("123") тус1аяя оЬ2 = "123"; соус « "оЫ: " « оЫ.песа() « евс(1; сонЯ « "оЬ2: " « оЬ2.деса() « епс)1; те"вгв О; Поскольку типы аргументов обоих конструкторов различны (как зто и должно быть) каждая инструкция инициализации автоматически преобразуется в соответствующий вызов конструктора. 2. Автоматическое преобразование на основе типа первого аргумента конструктора в вызов самого конструктора имеет интересное применение. Например, для класса пгус1авв из примера 1, чтобы присвоить объектам ев1 и еЬ2 новые значения, функция п)а(по выполняет преобразования из типа )п1 в тип с))аг '. ((ьпс1ис(е <ьовСкеаш> ((1пс1ис(е <сяМ)(Ь> ия)па пагпеярасе яМ; с1аьв птус1аьв ( (п1 а; роЫ1с." таус1авв(ьпс х) ( а = х; тпус1авв(сЬак +вст) ( а = агась(вск) г 407 Глана 13.
Пространства имен идругие темы (п( »7еТа() ( ге(пгп а; ) )и( пза1п () ( // преобразование в вызов конструктора вгус1аяя оЬ(4) вгус1аяя оЬ1 = 4; преобразование в вызов конструктора пус1аяя оЬ("123") тгу с1аья оЬ2 = "123"; сопя « "оЬ1; " « оЫ.г7еса() « ела; сопя « "оЬ2: " « оЬ2.гтеса() « епс?1г г'* использование автоматического преобразования для присваивания новых значений *» преобразование в вызов конструктора гпус1аяя оЬ("1776") лгус1аяя оЫ "177б"з преобразование в вызов конструктора гзус1аяя оЬ(2001) лгус1аяя оЫ = 2001; сонг « "оЫ: " « оЫ .гге~а() << епй1; сонг « "оЬ2: " « оЬ2.дева() « епй1; гег пгп 0; 3. Чтобы запретить показанные в предыдущих примерах преобразования, для конструкторов можно задать спецификатор ехрИс(1: ()1пс1пс?е <1ояйгеагв> Йг?пс1пг?е <сягг?1?Ь> ия?пд папгеярасе ягйг с1аяя иус1аяь ?пс а; риЫ1с; ехр1?с?с гпус1аяя(1пг х) ( а = хг ) ехр1?с?г звус1аяв(сЬаг *ясг) ( а = аТо1(ягг) з зпг г7еса() ( геспгп а; зп- вза1п() преобразование в вызов конструктора злус1аяя оЪ(4) глус1аяя оЫ =- 4; ггреобразование в вызов конструктора глус1аяя оЬ("123") лгус1аяя аЫ вЂ” "123"; Самоучитель С-г-г 4ОВ сонг « "сЬ1: " « оЫ .с(еьа(1 « епсП; соиЬ « "оЬ2: " « оЬ2,дега() « епд1; гегигп 0; 1.
В примере 3, если спецификатор ехр11с11 указать только для конструктора тус1аи((пй), можно ли будет выполнить неявное преобразование также и для конструктора тус1ааа(сваг 'ь)? (Подсказка: попробуйте и посмотрите, что получится.) 2. Работоспособен ли следующий фрагмент программы? с1авв 1)еп(о ( с1опЬ1 е Х,' рпЬ11.с: влепю (г(опЬ1е:(1 ( х = 1," 1 // // 1)епю сопи(ег - 10; 3. Попьпайтесь оправдать введение ключевого слова ехр11с!$. (Другими словами, объясните, почему неявное преобразование конструкторов в некоторых случаях может оказаться нежелательным.) 13.6. Спецификаторы сборки и ключевое слово авгп В С++ поддерживаются два важных механизма для облегчения связи С++ с другими языками программирования. Первым является слецификатор сборки ('//МаВе 5рес(/)ет), который сообщает компилятору, что одна или более функций вашей программы на С++ будет компоноваться с другим языком программирования, который может иметь другие соглашения о передаче параметров процедуре заполнения стека и т.
д. Вторым является ключевое слово аяп, которое позволяет вставлять в исходную профамму команды ассемблера. Оба этих механизма рассматриваются в этом разделе. По умолчанию все функции программы на С++ компилируются и компонуются как функции С++. Однако компилятору С++ можно сообщить, что функция будет компоноваться как функция, написанная на другом языке Глава 13. другие темы 409 Пространства имен и программирования. Все компиляторы С++ допускают компоновку функций либо как функций С, либо как функций С++. Некоторые также допускают компоновку функций для таких языков, как Разса!, Ада или ГОКТКАМ. Чтобы компоновать функции для других языков программирования, используется следующая основная форма спецификатора сборки: ех~етп "«анк"проооомп функции; Здесь язык — это название языка программирования, как функцию которого вы хотите компоновать вашу функцию.
Если необходимо использовать спецификатор сборки более чем для одной функции, используется такая его основная форма: ехйеюп 'язык" вроооокпзт Функций; Все спецификаторы сборки должны быть глобальными; их нельзя задавать внутри функций. Чаще всего в программы на С++ приходится вставлять фрагменты программ на С. Путем задания сборки с "С" вы предотвращаете искажения (тапИ1т~) имен функций информацией о типе. Поскольку в С++ имеется возможность перегружать функции и создавать функции-члены, то каждому имени функции обычно сопутствует некоторая информация о ее типе. С другой стороны, так как язык С не поддерживает ни перегрузки функций, ни функций-членов, он не может распознавать имена функций, искаженные информацией об их типе.
Указание компилятору необходимости сборки с "С" позволяет решить проблему. Хотя вполне возможно совместно компоновать ассемблерные подпрофаммы с программами на С++, часто легче использовать язык ассемблера в процессе написания программ на С++. В С++ поддерживается специальное ключевое слово аяп, позволяющее вставлять ассемблерные инструкции в функции С++. Преимущество встроенного ассемблера в том, что ваша программа полностью компилируется как программа на С++, и нет необходимости раздельно с ней компилировать, а затем совместно компоновать ассемблерные файлы. Здесь показана основная форма ключевого слова азш: ает ("ао ияооруицзик") р где ао ииоввзукция — это ассемблерная инструкция, которая будет встроена в вашу программу.