|
Программирование >> Полиморфизм без виртуальных функций в с++
для этого используется структурная эквивалентность. Я отдаю предпочтение эквивалентности имен, а не структур, потому что считаю такую модель наиболее безопасной. Поэтому мне было приятно узнать, что такое решение не противоречит С и не усложняет предоставление низкоуровневых услуг. Так появилось правило одного определения : каждая функция (переменная, тип, константа и т.д.) должна иметь в С++ ровно одно определение. 2.5.1 Простые реализации Желание иметь простую реализацию отчасти было вызвано необходимостью (для разработки С with Classes не хватало ресурсов), а отчасти обусловлено недоверием к излишне изощренным языкам и механизмам. Ранняя формулировка одной из целей проектирования С with Classes звучала так: для реализации языка должно хватать алгоритмов не сложнее линейного поиска . Любое нарушение этого правила - например в случае перегрузки функций (см. раздел 11.2) - приводило к семантике, которая мне казалась слишком сложной. А зачастую и к сложностям при реализации. Моей целью - памятуя опыт работы с Simula - было спроектировать язык достаточно простой для понимания, чтобы привлечь пользователей, и довольно простой в реализации, чтобы заинтересовать разработчиков компиляторов. С другой стороны, относительно несложная реализация должна была генерировать код, который не уступал бы С в корректности, скорости и величине. Пользователь, незнакомый с языком на практике и находясь в не очень дружелюбной среде разработки, тем не менее должен суметь воспользоваться компилятором в реальных проектах. Только при выполнении обоих этих условий можно было рассчитывать, что С with Classes, а позднее С++ выживут в конкуренции с С. Ранняя формулировка принципа звучала так: С with Classes должен быть неприхотливым сорняком вроде С или Fortran, поскольку мы не можем позволить себе ухаживать за такой розой , как Algol68 или Simula. Если мы создадим компилятор и на год уедем, то по возвращении хотелось бы увидеть его работающим хотя бы на нескольких системах. Этого не произойдет, если будет необходимо постоянное сопровождение или если простой перенос на новую машину зай.мет больше недели . Данный лозунг был частью философии - воспитывать в пользователях самостоятельность. Всегда, притом явно, ставилась задача вырастить местных экспертов по всем аспектам работы с С++. Кстати, большинство организаций вынуждено следовать противоположной стратегии - культивировать зависимость пользователей от услуг, приносящих доход центральной службе технической поддержки, консультантам или и тем, и другим одновременно. По моему мнению, здесь заключено фундаментальное отличие С++ от многих других языков. Решение работать в довольно примитивной - и почти повсеместно доступной - среде, обеспечивающей лишь компоновку в стиле С, породило большую проблему, связанную с тем, что компилятор С++ в любой момент времени имел лишь частичную информацию о программе. Каждое предположение опюситель-но программы может стать неверным, если завтра часть этой программы перепишут на каком-то другом языке (С, Fortran или ассемблере) и свяжут с остальными модулями, возможно, уже после того, как программа запущена в эксплуатацию. Данная проблема имеет многообразные проявления. Компилятору очень трудно гарантировать, что: □ объект, переме1П1ая и т.п. уникальны; □ информация непротиворечива (в частности, типы не конфликтуют); □ объект, пере.менная и т.п. инициализированы. Кроме того, в С есть лишь самая минимальная поддержка концепции раздельных пространств имен, так что проблемой становится загрязнение пространства имен из-за того, что части программ создаются разными людьми. Развивая С++, мы пытались ответить па все эти вызовы, не принося в жертву фундаментальную модель и технологию, которые обеспечили переносимость и эффективность; но во времена С with Cla.sses мы просто полагались на заголовочные файлы в стиле С. С принятием в качестве инструмента компоновщика, применяемого для программ на С, связано появление следующего правила: С++ - это просто еще один язык в системе, а не вся система. Други.ми слова.ми, он выступает в качестве традиционного языка программирования и принимает фундаментальные различия между языком, операционной системой и другими важными компонентами работы програ.ммиста. Это ограничивает языковые рамки, что довольно трудно сделать для таких языков, как Smalltalk или Lisp, задумывавшиеся как всеобъемлющие системы или среды. Очень важно, чтобы часть программы на С++ могла вызывать части, написанные на других языках, и сама могла быть вызвана. Кроме того, раз С++ - просто язык, то он .может применять инструменты, написанные для других языков. Тот факт, что язык программирования и написанный на нем код должны быть лишь шестеренкой внутри большого механизма, принципиально важен для большинства пользователей, работающих над про.мышленными проектами. Тем не менее многие теоретики, педанты и пользователи из акаде.мических кругов, очевидно, не учитывали, насколько важно мирное сосуществование одного языка с другими и с системами. Я думаю, что в этом одна из основных причин успеха С++. С with Classes почти совместим с С на уровне исходных текстов. Однако совместимость никогда не была стопроцентной. Например, class и new допустимы в С в качестве имен идентификаторов, но в С with Classes и его преемниках они являются ключевыми словами. Однако на уровне компоновки совместимость сохранена. Функции на С можно вызывать из С with Classes. Функции на С with Classes можно вызывать из С, а структуры одинаково раз1мещаются в памяти, следовательно, передача как простых, так и составных объектов между функциями, написанными на разных языках, проста и эффективна. Такая совместимость по компоновке сохранена и в С++, за несколькими простыми и явно обозначенными исключениями, которые програм.мист при желании легко может обойти (см. раздел 3.5.1). С года,ми я и мои коллеги пришли к выводу, что гораздо важнее совместимость на уровне компоновки, чем на уровне исходных текстов. По крайней мере, это верно, когда идентичный исходный код дает одни и те же результаты как в С, так и в С++, или не компилируется, или не связывается на одном из этих языков. Язык С with Classes 2.5.2. Модель размещения объекта в памяти Базовая модель объекта имела огромное значение для дизайна С with Classes. Я всегда точно представлял себе, как располагается объект в памяти, и рассматривал воздействие различных языковых средств на объекты. Без понимания эволюции модели объекта нельзя понять эволюцию С++. В С with Classes объект представлял собой просто С-структуру. Иными словами, объект class stack { char s [10]; char* min; char* top; char* max; void new(); public: void push(); char pop(); хранился в памяти так же, как структура struct stack { /* сгенерированный С-код */ char s[10]; char* min; char* top; char* max; to есть char s[10] char* min char* top char* max Компилятор может добавлять некоторые заполнители до и после членов структуры для выравнивания, но в остальном размер объекта равен сумме размеров членов. Таким образом, расход памяти минимизируется. Накладные расходы во время исполнения также сведены к минимуму за счет прямого отображения вызова функции-члена void stack.push(char с) { if (top>max) еггог( стек пуст ); *top++ = с; void g(class stack* p) { p->push(C);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |