- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
Одно из преимуществ, дарованных нам COM – динамическая загрузка компонентов. Причем загрузка экземпляров конкретных компонентов осуществляется на базе типов. Когда код загружен, программисты разрешают точки входа привязкой объектных ссылок к новым абстрактным типам. Для облегчения первого COM предоставляет CoCreateInstance как типо-ориентированную альтернативу файл-ориентированному вызову API LoadLibrary. Для облегчения последнего COM предоставляет метод QueryInterface как типо-ориентированную альтернативу символьно-ориентированному вызову API GetProcAddress. Посмотрите на следующий COM/C++ код:
IAntique *pAntique = 0;
HRESULT hr = CoCreateInstance(CLSID_Pinto, 0, CLSCTX_ALL, IID_IAntique, (void**)&pAntique);
if (SUCCEEDED(hr)) {
ICar *pCar = 0;
hr = pAntique->QueryInterface(IID_ICar, (void**)&pCar);
if (SUCCEEDED(hr)) {
hr = pCar->AvoidFuelTankCollision();
if (SUCCEEDED(hr)) {
hr = pAntique->Appreciate();
}
pCar->Release();
}
pAntique->Release();
}
Заметьте, что нигде нет вызовов LoadLibrary или GetProcAddress. Этот код избавлен от подробностей типа физического размещения DLL– библиотеки (мы даже не знаем, в DLL или в EXE хранится код компонента) или явного запроса адреса метода по символическому имени с последующим преобразованием адреса в указатель на функцию. Но этот код неуклюж и велик по сравнению с кодом создания экземпляра C++-класса и его приведения к базовому классу:
CPinto Antique;
CCar& Car = (CCar)Antique;
Car.AvoidFuelTankCollision();
Antique.Appreciate();
В чем же разница между этими листингами? В первом из них на языке программирования C++ был динамически создан экземпляр компонента, возможно, созданного на другом языке и располагающегося в отдельном исполняемом модуле, а во втором был создан экземпляр класса, определенного в той же программе (а значит, написанного на том же языке, располагающегося в том же модуле…). В остальном же эти листинги идентичны.
Ключ к пониманию недостатков COM спрятан именно в первом листинге. Этот код иллюстрирует напряженность между системой типов COM и системой типов языка реализации (в данном случае, C++). Заметьте, что везде, где объектная ссылка возвращается вызывающей стороне, ее должен сопровождать GUID (в этом примере IID_IAntique или IID_ICar). Это потому, что идентификатор типа языка реализации (std::type_info в случае C++) несовместим с форматом идентификатора типа COM.
За долгие годы группа C++ в Microsoft представила несколько технологий, позволяющих сгладить разницу между системами типов C++ и COM, самой важной (хотя и хитрой) из которых были расширения языка: __uuidof и declspec(uuid). Эти расширения позволили ассоциировать GUID (или, как его еще называют, UUID) с некоторым пользовательским типом. Компилятор MIDL при обработке IDL-файлов автоматически ассоциирует идентификатор типа (GUID) COM с символическим именем C++-типа. При использовании uuidof код становится более типобезопасным:
IAntique *pAntique = 0;
HRESULT hr = CoCreateInstance(__uuidof(Pinto), 0, CLSCTX_ALL, __uuidof(pAntique), (void**)&pAntique);
if (SUCCEEDED(hr)) {
ICar *pCar = 0;
hr = pAntique->QueryInterface(__uuidof(pCar), (void**)&pCar);
if (SUCCEEDED(hr)) {
hr = pCar->AvoidFuelTankCollision();
if (SUCCEEDED(hr)) hr = pAntique->Appreciate();
pCar->Release();
}
pAntique->Release();
}
Заметьте, что, если понадобится изменить тип pAntique, в первом листинге придется менять и IID, а во втором все произойдет автоматически, так как оператор __uuidof всегда получает нужный IID отталкиваясь от pAntique.
Более того, если воспользоваться возможностями самого C++, можно создать универсальные классы-обертки, еще более упрощающие жизнь программиста. Так при использовании CComPtr или поддержки COM компилятором (compiler COM support) можно написать примерно такой код:
CComPtr<IAntique> spIAntique;
HRESULT hr = spIAntique.CoCreateInstance(__uuidof(Pinto));
if (SUCCEEDED(hr)) {
CComQIPtr<ICar> spICar(spIAntique);
if (spIUnknown) hr = spICar->AvoidFuelTankCollision();
if (SUCCEEDED(hr)) hr = spIAntique->Appreciate();
}
Хотя этот код, несомненно, проще и безопаснее, он все же далек от идеала, причем как с точки зрения простоты и читабельности, так и с точки зрения типобезопасности. Ведь только во время исполнения программы будет точно известно, реализует объект эти интерфейсы или нет. Несмотря на использование __uuidof, чтобы заставить COM работать с C++, нужно отключить систему проверки типов C++ на время трансляции объектных ссылок COM в C++-типы. В отличие от этого, интеграция COM с виртуальной машиной Java Microsoft позволяет написать следующее:
IAntique antique = new Pinto();
ICar car = (ICar)antique;
car.AvoidFuelTankCollision();
antique.Appreciate();
Заметьте, что этот код наиболее близок к чистому коду на C++, разве что объект создается динамически, но компоненты и нельзя создавать на стеке.
Это пример, как и самый первый, загружает компонент на основании его типа, а не имени файла. Оба примера разрешают точки входа в компонент, используя средства приведения типов, а не символьные точки входа. Первое различие – Microsoft VM for Java выполняет огромную работу по состыковке системы типов Java с системой типов COM, и программистам не приходится делать этого вручную. Это и есть движущая сила для новой платформы – обеспечить универсальную среду исполнения компонентов, которой сможет воспользоваться любой компилятор, средство или служба. Новая среда – это и есть CLR!
А теперь взгляните на то, как выглядел аналогичный код в VB 6:
Dim thePinto as new Pinto, antique as IAntique
Set antique = thePinto
Dim car as ICar
Set car = antique
car.AvoidFuelTankCollision
antique.Appreciate
Сравните этот код с Java-кодом. На первый взгляд они идентичны, но не спешите делать окончательные выводы. Заметьте, что оператор Set в VB 6 кардинально отличается от приведения типов в Java. По сути Set аналогичен вызову QueryInterface (QI). Результат выполнения QI будет известен только на этапе выполнения, а приведение типа к базовому классу (интерфейсу) можно проверить еще на стадии компиляции.
Типобезопасность – это еще один постулат CLR.
Итак, CLR – это рантайм-среда, призванная упростить и обезопасить работу с компонентами для любого совместимого с ней средства или языка. Замечательно, скажете вы, но зачем же было ломать все и вся? Не лучше ли было подправить спецификацию COM, уточнить требования, предъявляемые к языкам программирования, ведь, например, VB совсем чуть-чуть не удовлетворяет этим требованиям? Это была бы, хотя и бурная, но эволюция. А так снова революция с неизбежным разрушением всего старого и с еще более неизбежной "наклепкой" всего нового. Причем это новое – не маленькая фитюлька, а то самое ВСЁ. На этот вопрос можно ответить, если задаться вопросом: а что, собственно, надо Microsoft? Постепенно улучшая свое программное обеспечение, с каждой новой версией доводить его до совершенства, тем самым поддерживать своих пользователей и зарабатывать уважение. Уважение?! А зачем оно Microsoft? Естественно, Microsoft жаждет не уважения, а господства, полного захвата рынка. Причем эти планы должны выполняться в среде открытой, практически честной конкуренции, где Microsoft может полагаться только на деньги, решительность и напористость.
При таком раскладе эволюция смерти подобна. Надо ломать при малейшем подозрении на несоответствие высоким идеалам, и строить заново. А уж если строить, то, конечно же, новый мир.
Есть и другое объяснения того, почему Microsoft так решительно отвергла все свои наработки и взялась за новую лучшую концепцию. Лучше всего эту версию изложил Ron Burk из WDJ. Вот его версия:
История программных революций от Microsoft, вкратце: Сначала были Windows API и DLL Hell. Революцией №1 было DDE – помните, как ссылки позволили нам создавать статусные строки, отражающие текущую цену акций Microsoft? Примерно тогда же Microsoft создала ресурс VERSION INFO, исключающий DLL Hell. Но другая группа в Microsoft нашла в DDE фатальный недостаток – его писали не они!
Для решения этой проблемы они создали OLE (похожее на DDE, но другое), и я наивно вспоминаю докладчика на Microsoft-овской конференции, говорящего, что скоро Windows API перепишут как OLE API, и каждый элемент на экране будет ОСХ-ом. В OLE появились интерфейсы, исключающие DLL Hell. Помните болезнь с названием "по месту", при которой мы мечтали встроить все свои приложения в один (возможно, очень большой) документ Word? Где-то в то же время Microsoft уверовала в религию C++, возникла MFC решившая все наши проблемы еще раз.
Но OLE не собиралась, сложа руки смотреть на это, поэтому оно заново родилось под именем COM, и мы внезапно поняли, что OLE (или это было DDE?) будет всегда – и даже включает тщательно разработанную систему версий компонентов, исключающую DLL Hell. В это время группа отступников внутри Microsoft обнаружила в MFC фатальный недостаток – его писали не они! Они немедленно исправили этот недочет, создав ATL, который как MFC, но другой, и попытались спрятать все замечательные вещи, которым так упорно старалась обучить нас группа COM. Это заставило группу COM (или это было OLE?) переименоваться в ActiveX и выпустить около тонны новых интерфейсов (включая интерфейсы контроля версий, исключающие DLL Hell), а заодно возможность сделать весь код загружаемым через броузеры, прямо вместе с определяемыми пользователем вирусами (назло этим гадам из ATL!).