Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 128 129 130 [ 131 ] 132 133 134 ... 144


your.h class Your ( public:

static char f(char);

static double f(double);

class String { /* ... */ };

К сожалению, и этот подход не лишен многих мелких неудобств. Не все глобальные объявления можно так просто перенести в класс, а некоторые от этого меняют семантику. Например, чтобы избежать изменений семантики, глобальные функции и переменные должны объявляться как статические члены, а тела функций и инициализаторы обычно следует отделять от объявлений.

17.3. Какое решение было бы лучшим?

Для решения проблем, связанных с пространством имен, можно воспользоваться разными механизмами. На самом деле, во многих языках имеются, по крайней мере, зачатки средств такого рода. Например, в С есть статические функций, в Pascal - вложенные области действия, в С++ - классы, но более полные решения следует искать в таких языках, как PL/I, Ada, Modula-2, Modula-3 [Nelson, 1991], ML [Wilkstrom, 1987] и СЮ5 [Kiszales, 1992].

Итак, что должен был бы дать языку С++ хороший механизм пространств имен? Продолжительная дискуссия рабочей группы по расширениям при комитете ANSI/ISO позволила составить целый список преимуществ. Вот эти возможности:

□ связь с двумя библиотеками без конфликтов и.мен;

□ введение имени без конфликта с чужими именами (например, из библиотеки, о которой я никогда не слышал, или неизвестны.ми мне именами из библиотеки, которую, как мне казалось, я знаю);

□ добавление новое имя в библиотеку без ущерба интересов пользователей;

□ использование имен из двух разных библиотек, даже если эти имена совпадают;

□ разрешение конфликтов имен без модификаций самих функций (только за счет манипулирования разрешением имен на уровне объявлений);

□ добавление нового имени в пространство имен, не опасаясь вызвать незаметного для пользователя изменения смысла кода, использующего другие пространства имен (мы не можем дать таких гарантий для кода, где используется пространство имен, в которое добавлено имя);

□ отсутствие конфликтов между именами самих пространств имен; в частности, реальное (видимое компоновщику) имя может быть длиннее имени, использованного в тексте программы;

□ применение механизма пространств к стандартным библиотекам;

□ совместимость с С и С++]

□ отсутствие издержек на этапе компоновки и во время выполнения при использовании пространств имен;



□ лаконичность пространств имен, не меньшая, чем при использовании глобальных имен;

□ явное указание в коде, из какого пространства должно быть взято имя.

Хорошее решение также должно быть простым. Под простотой я понимаю следующее:

□ чтобы механизм можно было сразу использовать для серьезных задач, на объяснение его работы должно уйти не более десяти минут. Чтобы объяснение удовлетворило языковых пуристов, может потребоваться гораздо больше времени;

□ разработчик компилятора должен быть способен реализовать этот механизм менее чем за две недели.

Разумеется, простоту здесь нельзя понимать строго, ведь людям с разной подготовкой и способностями для усвоения одного и того же материала требуется неодинаковое время.

Есть также несколько свойств, которые мы сознательно решили исключить из списка критериев, хотя об их включении часто просили:

□ возможность взять два объектных файла с конфликтующими именами и связать их вместе. Это могут сделать инструментальные средства в любой системе, но неясно, как можно было бы реализовать для этого языковую поддержку без значительных затрат. Существует слишком много компоновщиков и форматов объектных файлов, чтобы рассчитывать на их приведение к общему стандарту. Чтобы решение было полезным для С++, оно должно зависеть только от возможностей, предоставляемых практически всеми современными компоновщиками;

□ возможность назначать произвольные синонимы именам, используемым в библиотеках. Существующие механизмы - typedef, ссылки и макросы -позволяют это делать в некоторых ситуациях, а универсальным средствам переименования я не доверяю (см. раздел 12.8).

Отсюда следует, что механизм устранения неоднозначности должен быть встроен в объектный код авторами отдельных фрагментов програ.ммы. В частности, поставщикам библиотек придется использовать какой-то метод, который дал бы возможность пользователям разрешить неоднозначность. К счастью, именно поставщики библиотек больше всего выигрывают от систематического использования пространств имен.

Разумеется, этот перечень можно продолжать, и многие наверняка не согласны с оценкой относительной важности каждого критерия. Тем не менее список дает представление о сложности задачи и о требованиях, которым должно удовлетворять решение.

Изложив все критерии, я получил возможность проверить, в какой мере проектирование пространств имен отвечает требованиям простоты. Питер Джуль выполнил первую реализацию за пять дней, а мне менее чем за десять минут удалось объяснить основы механизма пространств имен нескольким пользователям. Заданные вопросы показали, что мои ученики усвоили суть и смогли самостоятельно



додуматься до таких применений пространств имен, которые я вообще не объяснял. Итак, механизм оказался достаточно простым. Опыт последующей реализации, обсуждение концепции пространств имен и некоторые их приложения утвердили меня в этом мнении.

17.4. Решение: пространства имен

Принятое решение в принципе очень просто. Оно дает четыре новых .механизма;

□ механизм определения области действия, обобщающий глобальные объявления в С и С++: пространства имен. Такие области действия разрешается именовать, а к их членам можно обращаться с помощью обьшного для членов класса синтаксиса: namespace name: :meinber name, где namespace name -имя пространства имен, а member name - имя члена. Фактически область действия класса можно считать частным случаем области действия пространства имен;

□ механизм определения локального синонима для имени из пространства имен;

□ механизм, позволяющий обратиться к одному члену пространства имен, не указывая имя пространства имен, то есть опуская префикс namespace name: : . Это достигается использованием using-объявления;

□ механизм, позволяющий обращаться ко всем членам пространства имен, не указывая явно имя самого пространства имен. Достигается использованием using-директивы.

Тем самым удовлетворяются все критерии, приведенные в разделе 17.3. Кроме того, решается давний вопрос о том, как обратиться к членам базового класса из области действия производного класса (см. разделы 17.5.1 и 17.5.2). Заодно становится избыточным атрибут static для глобальных имен (см. раздел 17.5.3).

Рассмотрим пример:

namespace А { void f(int); void f(char);

class String { /* ... */ }; ...

Имена, объявленные внутри фигурных скобок, принадлежат пространству имен А и не конфликтуют ни с глобальными именами, ни с именами из других пространств имен. Объявления внутри пространства имен (в том числе, и определения) имеют в точности ту же семантику, что и глобальные объявления, но их область действия ограничена этим пространством имен.

Программист может использовать такие имена, добавляя явный квалификатор:

А::string sl = Annemarie ;

void glO {

A::f (1);



1 ... 128 129 130 [ 131 ] 132 133 134 ... 144

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика