Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 5
На сайте нет зарегистрированных пользователей

Пользователей: 13,372
новичок: vausoz
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Информационная система - продуктовый магазин на Turbo Pascal (База данны...
Моделирование процесса обработки заданий пакетным режимом работы с квант...
Моделирование литейного цеха на GPSS + Пояснительная записка

Инкапсуляция и С++



Предположим, что вам удалось преодолеть проблемы с транслятором и компоновщиком, описанные в предыдущем разделе. Очередное препятствие при построении двоичных компонентов на C++ появится, когда вы будете проводить инкапсуляцию (encapsulation), то есть формирование пакета. Посмотрим, что получится, если организация, использующая FastString в приложении, возьмется выполнить невыполнимое: закончит разработку и тестирование за два месяца до срока рассылки продукта. Пусть также в течение этих двух месяцев некоторые из наиболее скептически настроенных разработчиков решили протестировать O(1) -поисковый алгоритм FastString , запустив профайлер своего приложения. К их большому удивлению, FastString::Find стала бы на самом деле работать очень быстро, независимо от заданной длины строки. Однако с оператором Length дело обстоит не столь хорошо, так как FastString::Length использует подпрограмму strlen из динамической библиотеки С. Эта подпрограмма – алгоритм O(n) – осуществляет линейный поиск по строкам с использованием символа конца строки (null terminator); скорость его работы пропорциональна длине строки. Столкнувшись с тем, что клиентское приложение может многократно вызывать оператор Length , один из таких скептиков, скорее всего, свяжется с разработчиком библиотеки и попросит его убыстрить Length , чтобы его работа также не зависела от длины строки. Но здесь есть одно препятствие. Разработчик библиотеки уже закончил свою разработку и, скорее всего, не расположен менять одну строку исходного кода, чтобы воспользоваться преимуществами улучшенного метода Length . Кроме того, некоторые другие разработчики, возможно, уже выпустили свои продукты, основанные на текущей версии FastString , и теперь разработчик библиотеки не имеет морального права изменять эти приложення.
С этой точки зрения нужно просто вернуться к определению класса FastString и решить, что можно изменить и что необходимо сохранить, чтобы уже установленная база успешно функционировала. К счастью, класс FastString был разработан с учетом возможности инкапсуляции, и все его элементы данных ( data members ) являются закрытыми ( private ). Это придает классу значительную гибкость, так как ни одна клиентская программа не может непосредственно получить доступ к элементам данных FastString . В силу того, что по отношению к четырем открытым ( public ) членам класса не было сделано никаких изменений, то и в любом клиентском приложении никаких изменений также не потребуется. Вооружившись этой верой, разработчик библиотеки переходит к реализации FastString версии 2.0.
Очевидным улучшением является следующее решение: в тексте конструктора ( constructor ) занести длину строки в кэш и возвращать кэшированную длину в новой версии метода Length . Так как строка не может быть изменена после создания, нет необходимости беспокоиться, что ее длина будет вычисляться многократно. В действительности длина уже однажды вычислена в конструкторе при назначении буфера, так что понадобится только горстка дополнительных машинных инструкций. Вот каким будет модифицированное определение класса:
// faststring.h version 2.0
class declspec(dllexport) FastString {
const int mcch;
// count of characters
// число символов
char mpsz;
public:
FastString(const char *psz);
~FastString(void);
int Length(void) const;
// returns # of characters
// возвращает число символов
int Find(const char *psz) const;
// returns offset – возвращает смещение
};



Отметим, что единственной модификацией является добавление закрытого элемента данных. Чтобы правильно инициализировать такой элемент, конструктор должен быть изменен следующим образом:
FastString::FastString(const char *psz) : mcch(strlen(psz)), mpsz(new char[mcch + 1])
{
strcpy(mpsz, psz);
}



С введением кэшированной длины метод Length становится тривиальным:
int FastString::Length(void) const
{
return mcch;
// return cached length
// возвращает скрытую длину
}



Сделав эти три модификации, разработчик библиотеки может теперь перестроить DLL FastString и сопутствующий ей набор тестов, которые полностью проверяют каждый аспект класса FastString . Разработчик будет приятно удивлен, узнав, что принцип инкапсуляции обошелся ему дешево, и в исходных текстах тестов не понадобилось делать никаких изменений. После проверки того. что новая DLL работает правильно, разработчик библиотек отсылает FastString версии 2.0 клиенту, будучи уверенным, что вся работа завершена.
Когда клиенты, заказавшие изменения, получают модернизированный FastString , они включают новое определение класса и DLL в систему контроля своего исходного кода и запускают тестирование нового и улучшенного FastString . Подобно разработчику библиотеки, они тоже приятно удивлены: для того, чтобы воспользоваться преимуществами новой версии Length , не требуется никаких модификаций исходного кода. Вдохновленная этим опытом, команда разработчиков убеждает начальство включить новую DLL в окончательный «золотой» CD, уже готовый для выпуска. Это тот редкий случай, когда руководство идет навстречу энтузиастам-разработчикам и включает в окончательный продукт новую DLL. Подобно большинству программ инсталляции, описание установки клиентской программы настроено на молчаливое (без предупреждения) замещение всех старых версий FastString DLL, какие есть на машине конечного пользователя. Это выглядит вполне безобидно, поскольку эти изменения не затронули открытый интерфейс класса, так что тотальная молчаливая модернизация под версию 2.0 FastString только улучшит любые имеющиеся клиентские приложения, которые были установлены раньше.
Представим себе следующий сценарий: конечные пользователи наконец-то получают свои экземпляры вожделенного продукта. Каждый из них тут же бросает все и устанавливает новое приложение на свою машину, дабы попробовать его. После того как высохли слезы восторга от того, что наконец-то можно делать быстрый текстовый поиск, пользователь возвращается к его или ее нормальному состоянию и запускает ранее установленное приложение, которое также имеет неосторожность использовать DLL FastString . Первые несколько минут всё идет хорошо. Затем внезапно появляется сообщение, что возникла исключительная ситуация и что вся работа конечного пользователя пропала. Он пытается запустить приложение снова, но на этот раз диалоговое окно об исключительной ситуации появляется почти сразу. Конечный пользователь, привычный к употреблению современного программного обеспечения, переустанавливает операционную систему и все приложения, но даже это не спасает от повторения исключительной ситуации. Что же произошло?
А произошло то, что разработчик библиотеки был убаюкан верой в то, что C++ поддерживает инкапсуляцию. Хотя C++ и поддерживает синтаксическую инкапсуляцию через свои закрытые и защищенные ключевые слова, в стандарте C++ ничего не сказано о двоичной инкапсуляции. Это происходит потому, что модель трансляции C++ требует, чтобы клиентский компилятор имел доступ ко всей информации относительно двоичного представления объектов, – с целью обработать экземпляр класса или делать невиртуальные вызовы метода. Это включает в себя информацию о размере и порядке закрытых и защищенных элементов данных объекта. Рассмотрим сценарий, показанный на рис. 1.3. Версия 1.0 FastString требует четыре байта на экземпляр (принимая sizeof(char *) == 4 ). Клиенты написанного под версию 1.0 определения класса выделяют четыре байта памяти под вызов конструктора класса. Конструктор, деструктор и методы версии 2.0 (а именно эти версии содержатся в DLL в машине конечного пользователя) ожидают, что клиент выделил восемь байт на экземпляр (принято sizeof(int) == 8 ), и не предусматривают собственных резервов для записи во все восемь байт. К сожалению, у клиентов с версией 1.0 вторые четыре байта этого объекта на самом деле принадлежат кому-то другому, и запись в это место указателя на текстовую строку недопустима, о чем и сообщает диалог исключительной ситуации.
Существует общее решение проблемы версий – переименовывать DLL всякий раз, когда появляется новая версия. Такая стратегия принята в Microsoft Foundation Classes (MFC). Когда номер версии включен в имя файла DLL (например, FastString10.DLL , FastString20.DLL ), клиенты всегда загружают ту версию DLL, с которой они были сконфигурированы, независимо от присутствия в системе других версий. К сожалению, со временем, из-за недостаточного опыта в системном конфигурировании, число версий DLL, имеющихся в системе конечного пользователя, может превысить реальное число пользовательских приложений. Чтобы убедиться в этом, достаточно проверить системный каталог любого компьютера, проработавшего больше шести месяцев.
В конечном счете, проблема управления версиями коренится в модели трансляции C++, не рассчитанной на поддержку независимых двоичных компонентов. Требуя знания клиентом двоичного представления объектов, C++ предполагает тесную двоичную связь между клиентом и исполняемыми программами объекта. Обычно такая связь является преимуществом C++, так как она позволяет трансляторам генерировать весьма эффективный код. К сожалению, эта тесная двоичная связь не позволяет переместить реализации класса без проведения клиентом повторной компиляции. По причине этой связи и несовместимости транслятора и компоновщика, упомянутых в предыдущем разделе, простой экспорт определений класса C++ из DLL не обеспечивает приемлемой архитектуры двоичных компонентов.
Опубликовал Kest July 10 2009 20:30:24 · 0 Комментариев · 8554 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
BIOS
Averaging [Исходн...
PHP/MySQL для нач...
Adapter (пример D...
Эффект лампы на р...
Error mod
Интерактивный инт...
DeleteEdit
Пример работы с ф...
XPcontrol
Szwavepanel
Простой текстовый...
MPTools
AID антивирус
ActiveX в Delphi
Web Регистрация
PHP: Полезные приемы
Трассировка прово...
ScreenSaver [Исхо...
Конвертирование и...

Топ загрузок
Приложение Клие... 100794
Delphi 7 Enterp... 98040
Converter AMR<-... 20298
GPSS World Stud... 17060
Borland C++Buil... 14246
Borland Delphi ... 10376
Turbo Pascal fo... 7393
Калькулятор [Ис... 6084
Visual Studio 2... 5236
Microsoft SQL S... 3674
Случайные статьи
Трояны - это свои ...
Определение шаблон...
Табл. 15-6.
Слот-автоматы
Пример добавления ...
В случае атаки сис...
Пример приложения ...
аутентификацию по ...
Функция сохранени...
Расстановка, или С...
Поток без синхрони...
Женская психология
tldЧтобы регистрир...
Функция GetDriverN...
Содержание
Добавление отдельн...
Стандарт POSIX
Добавление в проек...
Виртуальное казин...
Объемные диаграммы
Оптимизация програ...
компьютеры клиенто...
Решения к главе 15
Алгоритмы обхода б...
Как работает типов...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?