|
Программирование >> Полиморфизм без виртуальных функций в с++
Модификатор readonly служит для предотврощения изменения переменной. Он показы-воет, что из всех способов доступа к переменной зоконны только те, которые не изменяют ее значения . Далее в записке говорится: Модификатор readonly применим также и кукозотелям. * readonly интерпретируется как неизменяемый указатель но . Например: readonly int * р; /* указатель на int только для чтения */ int * readonly pp; /* неизменяемый указатель на int */ readonly int * readonly ppp; /* неизменяемый указатель на */ /* int только для чтения */ В этих примерах допустимо присвоить новое значение р, но не *р. Можно присвоить зно-чение *рр, но не pp. Ни ррр, ни *ррр зночение присвоить нельзя . В той же записке введено понятие о writeonly: Модификотор типо writeonly анологичен readonly, только зопрещает чтение, о не зопись. Нопример: struct device registers { readonly int input reg, status reg; writeonly int output reg, coiiimand reg; void f(readonly char * readonly from, writeonly char * readonly to) f может получить данные через from, сохранить результаты в to, но не может изменить ни тот, ни другой указатель /* ... */ int * writeonly р; Здесь ++Р недопустимо, ток как в кочестве побочного эффекте подразумевает чтение предыдущего значения р, но р=0 допустимо . Это предложение акцентировало внимание на определении интерфейса, а не на включении в С символических констант. Ясно, что значение с модификатором readonly - это символическая константа, но идея была шире. Первоначально я предлагал указатели на readonly, но не readonly-указатели. Благодаря короткой дискуссии с Деннисом Ричи возникла идея о механизме readonly/ writeonly, который был реализован и предложен внутренней группе по стандартизации С в стенах Bell Labs под председательством Ларри Рослера. Это мой первый опыт работы над стандартами. Покидая совещание, я имел договоренность (то есть принятое большинством решение), что readonly будет включено в С -да-да, именно в С, а не в С with Classes или С++, следует только переименовать его в const. К сожалению, подобные решения ни к чему не обязывают, вот почему с нашими компиляторами С ничего не произошло. Позже был образован комитет ANSI С (X3J11), предложение о введении const было представлено на его рассмотрение и стало частью ANSI/ISO С. Между тем я продолжил эксперименты с const в С with Classes и обнаружил, что этот модификатор может служить заменой макросам для представления констант, только если глобальные const-объекты используются как локальные в своих единицах компиляции. Лишь в этом случае компилятор мог без труда сделать вывод, что значение const-объектов действительно не изменится. Знание этого факта позволяет использовать простые const-объекты в константных выражениях, не выделяя под них память. В С это правило оказалось непринятым. Например, в С-ы- можно написать const int max = 14,- void f{int i) int a[max+l]; константа max используется в константном выражении switch (i) { case max: константа max используется в константном выражении ... тогда как в С (даже сегодня) необходимо fdefine max 14 ... поскольку, в с не разрешается использовать const-объекты в константных выражениях. Из-за этого модификатор const в С не так полезен, как в С++. Язык С остается зависимым от препроцессора, тогда как программистам на С-ы- доступны типизированные константы с ограниченной областью действия. 3.9. Управление памятью Задолго до того как была написана первая программа на С with Classes, я знал, что свободная (динамическая) память в языке с классами будет использоваться гораздо интенсивнее, чем в С. По этой причине в С with Classes и были введены операторы new и delete. Оператор new, который одновременно выделяет память и инициализирует ее, заимствован из языка Simula. Оператор delete был необходимым дополнением, поскольку я не хотел, чтобы С with Classes зависел от сборщика мусора (см. разделы 2.13 и 10.7). Изложу аргументацию в пользу оператора new. Какая запись вам больше нравится, такая: X* р = new X(2); struct X * р = (struct X *) malloc(sizeof(struct X)); if (p == 0) еггогСне хватило памяти ); p->init(2); И где проще сделать ошибку? Отметим, что проверка на нехватку памяти ведется в обоих случаях. Только оператор new при выделении памяти делает это неявно и может вызывать написанную пользователем функцию new handler [2nd, §9.4.3]. В то время достаточно часто звучали аргументы против: нам это ни к чему и ведь кто-то мог уже использовать new как идентификатор . Разумеется, и то, и другое правильно. Итак, введение оператора new упростило работу со свободной памятью и сделало ее менее подверженной ошибкам. Это способствовало широкому распространению оператора, поэто.му из-за функции выделения па.мяти malloc () из библиотеки С, использованной в реализации new, значительно снижалась производительность программы. Само по себе это не удивительно; вопрос - что с .этим делать? То, что реальные программы тратили 50% времени и даже больше внутри malloc (), было абсолютно неприемлемым. Я пришел к выводу, что очень эффективны операторы распределения и освобождения памяти, определенные в классе. Основная идея заключалась в то.м, что свободная память, как правило, выделяется и освобождается для большого числа маленьких объектов, принадлежапщх небольшому числу классов. Вынесите выделение памяти для таких объектов в отдельную функцию-распределитель, и тогда можно будет сэкономить и время, и память, а заодно уменьшить фрагментацию свободной памяти общего назначения. Вспо.минаю, как излагал Брайану Кернигану и Дугу Макилрою прием присваивания указателю this (описан ниже) и резюмировал свою речь так: Это уродливо, как смертный грех, но работает, и если у вас нет лучших предложений, то именно так я это и реализую . Предложений у них не оказалось, так что более красивого решения нам пришлось ждать до выхода версии 2.0, уже в С++ (см. раздел 10.2). По умолчанию память для объекта выделялась системой , не требуя от пользователя никаких действий. Чтобы отменить это, программист просто должен был присвоить значение указателю this. По определению this указывает на объект, для которого вызвана функция-член. Например: class X { ... public: x(int i); . . . X::X(int i) this = my alloc(sizeof(X)); инициализация
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |