|
Программирование >> Полиморфизм без виртуальных функций в с++
void reverse(int* elements, int length of element array); ... void reverse{int* v, int n) { . . . Как всегда, одни находят такой стиль отвратительным, другие (в том числе я) - вполне разумным. Как бы то ни было, програ.мм в указанно.м стиле написано очень .много. Но, введя именованные аргу.меиты, мы не сможем изменить ни одно имя в стандартно распрострапяемо.м заголовочно.м файле без риска сделать неработоспособным пользовательский код. Поставщика.м заголовочных файлов для одних и тех же библиотек, папри.мер Posix или X Windows, придется договариваться об и.менах аргументов. Но можно сделать так, чтобы в языке не было требования одинаково именовать один и тот же аргу.мент в объявлениях. Такой вариант казался мне приемлемым. Однако другим он не понравился. Если требовать проверки того, что имена аргументов одинаковы в разных единицах трансляции, то время компоновки может существенно увеличиться. Если же не организовывать такой проверки, под угрозой окажется безопасность типов, что .может стать источником скрытых ошибок. И потенциальную проблему замедления компоновки, и вполне реальную проблему дополнительных зависи.мостей можно было бы решить, опустив имена аргументов в заголовочных файлах. Тогда осмотрительный пользователь мог бы не задавать та.м имена аргументов, но, цитируя Билла Гиббонса, это может негативно сказаться на удобочитаемости програм.м на С++ . Я опасался, что и.менованные аргументы могут замедлить постепенный переход от традиционных приемов программирования к абстракции данных и далее к объектно-ориентированному стилю. В профам.мах, которые, на мой взгляд, лучше всего написаны и удобны для сопровождения, длинные списки аргументов -редкость. Многие пользователи отмечали, что переход к объектно-ориентированному стилю сопровождается укорачиванием списков аргументов: то, что раньше передавалось в виде аргументов или глобальных переменных, теперь становится локальным состоянием объекта. Основываясь на опыте, я ожидаю, что среднее число аргу.ментов будет меньше двух, а функций, и.меющих более двух аргументов, почти не останется. Отсюда следует, что именованные аргументы окажутся наиболее полезными как раз в таких программах, которые мы считаем написанными плохо. Так следует ли вводить новое средство, поощряющее и.менпо тот стиль программирования, который мы хотели бы изжить? Такая постановка вопроса, проблема сов.мести.мости и некоторые мелкие детали стали причиной единодушного отказа принять предложение об именованных аргументах. 6.5.1.1. Альтернативы именованным аргументам Но если мы отказываемся от именованных аргу.ментов, то как сократить длину списка аргу.ментов в примере с классо.м window? Кажущаяся сложность уже class bordered window : public window { public: bordered window(border b=single, color bc=blue) : window(standard,0,0,100,100,black,b,be) { } Этот прием ограничивает использование функции несколькими наиболее употребительными формами и потому код и поведение программы становятся более однообразньши. Другой способ - ввести явные операции для задания установок, отличных от подразумеваемых: class w args { wintype wt; int ulcx, ulcy, xz, yz; color wc, be; border b; WSTATE ws; public: w args() установки no умолчанию : wt(standard), ulcx(O), ulcy(O), xz(lOO), yz(lOO), wc(black), b(single), bc(blue), ws(open) { } отменить умолчания: w args& ysize(int s) { yz=s; return *this; } w args& Color(color c) { wc=c; return *this; } w args& Border(border bb) { b = bb; return *this; } w args& Border color(color c) { bc=c; return *this; } . .. class window { . . . window(w args wa); CKonnposaTb настройки wa . . . Это дает нам нотационное удобство, в некоторой степени эквивалентное тому, которое обеспечивают именованные аргументы: window w; окно по умолчанию window w( w argsО.Color(green).ysize(150) ); уменьшена за счет аргументов по умолчанию. Еше один распространенный прием - дополнительные типы для представления наиболее типичных вариантов: class colored window : public window { public: colored window{color c=black) : window{standard,0,0,100,100,c) { } Существенное преимущество такого способа состоит в том, что он облегчает передачу объектов, представляющих аргументы, между различными частями программы. Естественно, все эти приемы можно использовать в любом сочетании. В совокупности они позволяют сократить список аргументов и, следовательно, свести иа нет потреб1Юсть в именованных. Число аргументов можно еще больше сократить, если воспользоваться типом Point, вместо того чтобы передавать пары координат. 6.5.2. Ограниченные указатели Компилятору Fortran разрешено предполагать, что два массива, переданных функции в качестве аргументов, пе перекрываются. Функция С++ не вправе делать таких допущений. В результате подпрогра.мма, написанная на Fortran, оказывается на 15-30% быстрее в зависимости от качества компилятора и машинной архитектуры. Особенно заметную экономию дают векторные операции на машинах, имеющих специальную векторную аппаратуру (например, Cray). Учитывая повышенное внимание к эффективности С, все вышесказанное рассматривалось, как досадная оплошность. В комитет ANSI С поступило предложение решить эту проблему с помощью механизма, названного пса lias. При наличии этого ключевого слова считалось бы, что у указателя нет псевдонимов (то есть никакие два указателя не указывают на одну и ту же область памяти). К сожалению, предложение поступило слишком поздно и в очень непроработанном виде. Это обстоятельство побудило Денниса Ричи написать открытое письмо, начинающееся слова.ми: никаких noalias, это даже не подлежит обсуждению . Понятно, что после этого сообщество пользователей С и С++ без особой охоты возвращалось к проблеме псевдонимов. Но вопрос был очень важен для пользователей С на платформе Cray, поэтому Майк Холли (Mike Holly) из компании Cray, в конце концов, представил улучшенное предложение по этой проблеме группе по численным расширения.м С (NCEG) и комитету по С++. Идея заключалась в том, чтобы дать программисту возможность декларировать отсутствие у указателя псевдонимов, объявив его с ключевым словом restrict: void* memcopy{void*restrict sl, const void* s2, size t n); Поскольку уже сказано, что у sl нет псевдонимов, нет необходимости указывать restrict еще и для s2. Ключевое слово restrict применяется к оператору * точно так же, как модификаторы const и volatile. Это предложение должно устранить преимущество Fortran в эффективности, приняв в С правила, действующие в Fortran (правда, лишь выборочно). Комитет по С++, внимательно относившийся к любому предложению, способному повысить эффективность языка, потратил немного времени на обсуждение данного предложения, но все же оно было отклонено, насколько я помню, единогласно. Вот основные мотивы: □ расширение небезопасно. Если объявить указатель как restrict, то компилятору позволено предполагать, что у него пет псевдонимов. Од!1ако
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |