Введение
Разработчик
приложений, решивший воспользоваться услугами Visual Studio.Net 7.0, получает
в свое распоряжение достаточно много новых технологий и инструментов, которые
позволяют ему быстро и эффективно создавать обычные Windows-приложения, которые
теперь принято называть настольными — desktop applications, а также web-приложения
и web-услуги (Web Services). Компания Microsoft добавила в арсенал программиста
новый язык С# (произносится «Си шарп»), который, как обещают специалисты, способен
в несколько раз ускорить цикл разработки сложных проектов.
Главной новостью,
которая должна привлечь ваше внимание, является то, что Visual C++, Visual Basic
и С# используют одну и ту же среду разработки IDE (Integrated Development Environment),
что дает возможность создавать комплексные проекты с использованием разных языков
(mixed-language solutions). Многоязыковая среда разработки .Net (.Net Framework)
представляет собой сумму трех составляющих:
Первая составляющая
— библиотека времени исполнения (Common Language Runtime, сокращенно CLR), функционирует
как на этапе выполнения, так и на этапе разработки. Во время выполнения кода
она следит за динамикой многопотоковых приложений, обеспечивает взаимосвязь
процессов, поддерживает их безопасность, автоматизирует процедуры выделения
и освобождения памяти. На этапе разработки CLR автоматизирует типовые задачи,
решаемые программистом, значительно упрощая использование новых технологий.
Особо отмечаются преимущества, получаемые при создании компонентов стандарта
COM (Component Object Model, сокращенно COM — Модель многокомпонентных объектов).
Вторая составляющая
(Unified Programming Classes) предоставляет разработчику унифицированную, объектно-ориентированную,
расширяемую библиотеку классов, которая совместно с другими ресурсами является
частью программируемого интерфейса приложений API (Application Programming Interface).
Она объединяет элементы MFC (Microsoft Foundation Classes), WFC (Windows Foundation
Classes) и часть API, используемую Visual Basic.
Третья составляющая
(ASP.Net) представляет собой надстройку на.д классами, которая дает возможность
пользоваться объектно-ориентированной технологией при разработке типовых элементов
HTML-интерфейса. Фактически выполняемые на стороне сервера, эти элементы проецируют
функции пользовательского интерфейса в виде HTML-кода. Однако при разработке
сервера имеется возможность
использовать мощный аппарат, предоставляемый объектной моделью программирования.
Результат — резкое упрощение процесса построения web-приложений. В дополнение
к этому ASP.Net поддерживает достаточно новую концепцию или модель разработки
программ. Вы, наверное, слышали о ней, как о технологии «тонкого» клиента. Основная
суть этой модели — предоставление кода пользователю не в виде инсталлируемого
продукта, а в виде временной услуги (service).
Код, который создан на основе среды разработки .Net Framework, носит название управляемого кода {managed code) в отличие от обычного, неуправляемого кода (unmanaged code). В режиме .Net компиляторы рассмотренных языков производят метаданные (metadata), которые сопровождают сам код. Это означает, что они генерируют дополнительную информацию, описывающую типы данных, объекты и ссылки. Библиотека времени исполнения (Common Language Runtime) использует метаданные для поиска и загрузки объектов, запуска функций, передачи параметров, размещения объектов в памяти.
Важной функцией, которую выполняет библиотека времени исполнения, является автоматическое освобождение памяти, занимаемой объектами, которые более не используются. Это нововведение призвано повысить надежность как отдельных компонентов, так и всего разрабатываемого приложения. Данные, время жизни которых управляется таким образом, называются управляемыми данными (managed data). Если ваш код является управляемым (managed code), то вы можете пользоваться управляемыми данными, но можете и не использовать их. Более того, вы можете и не знать, являются ли ваши данные управляемыми.
Общая библиотека времени исполнения (CLR) упрощает создание приложений и их составляющих, которые разработаны на разных языках и настроены (target) на использование CLR. Эти модули могут быть интегрированы в одном проекте и взаимодействовать между собой так, как будто они были созданы на одном языке. Например, вы можете декларировать класс, а затем создать производный от него класс уже на другом языке. Можно и просто пользоваться методами класса в рамках модуля, написанного на другом языке. Такая интеграция стала возможной потому, что компиляторы и инструменты разных языков пользуются общей системой типов, определенной в CLR, а также новыми правилами игры, принятыми при ее разработке.
Управляемые расширения для C++
Так называется
множество расширений языка C++. Они были введены с целью помочь разрабатывать
приложения, ориентированные на платформу Microsoft.Net. Традиционный (unmanaged)
код C++ и управляемый код (managed) могут одновременно присутствовать в одном
приложении, не мешая друг другу. Для того чтобы получить быстрое представление
об этой технологии, рассмотрим пример. Вы начинаете со стартовой заготовки Visual
C++ Projects, скроенной по шаблону Managed C++ Application, задав имя проекту
(например, Man), и получаете два СРР-
файла: Мап.срр
и Assemblylnfo.cpp. Первый файл представляет собой заготовку вашей программы
консольного типа:
//=== Импортирует метаданные в программу, использующую
//=== Managed Extensions for C++
#using <mscorlib.dll>
// Стало доступным пространство имен System, которое
// содержит описания фундаментальных классов, атрибутов,
// интерфейсов и событий
using namespace
System;
int main (void)
{
// Console — это класс, который обеспечивает стандартные
// операции ввода-вывода
в окно консольного типа
Console::WriteLine("Hello
World");
return 0;
}
Второй файл
содержит атрибуты настройки сборочной информации (assembly metadata). Коды этого
файла нет смысла рассматривать, так как они носят сугубо служебный характер.
Вы можете запустить программу на выполнение (Ctrl+F5) и увидеть традиционное
приветствие в окне консольного типа. Теперь покажем, как можно создать управляемый
динамический массив. Вставьте директиву finclude <stdlib.h> и отредактируйте
код главной функции:
void main()
{
// Описатель
_gс декларирует garbage-collected object,
// то есть объект,
за памятью которого будет следить CLR
int managed
_gc[] = new int _gc[rand()%100 + 1);
//==== Обычный
динамический массив
int *unmanaged
= new int[rand()%100 + 1];
//==== Мы можем задавать вопросы объекту managed
Console::WriteLine (managed->Count);
Console::WriteLine
(managed->Rank);
//==== Мы не можем задавать вопросы объекту unmanaged
}
Запустите
проект и убедитесь в том, что в окне выведены два числа, 42 и 1. Первое число
является случайно выбранным размером массива (managed), а второе — рангом массива,
то есть его размерностью (одномерный массив). Для того чтобы чуть-чуть глубже
проникнуть в тайны управляемого кода и данных, дополните тестовую программу
кодами нового управляемого класса Man. Вставьте следующие коды до функции main.
Что-то от
Java или Visual Basic? Нет, это — managed C++!
public
_gc
class Man
// Эта строка ничем не отличается от C++
{
private:
//=== String — новый мощный класс для работы с текстом
String *m_Name;
// Имя
int m_Age;
// Возраст
public:
//==== Конструкторы
Man ()
{
m_Name = S "Dummy";
m_Age = 0;
}
Man (String* n, int a)
{
m_Name = n;
m Age = a;
}
//==== Два метода
доступа к закрытым данным
String* GetName()
{
return m_Name;
}
int GetAge ()
{
return m_Age;
}
};
Теперь опробуйте
работу нового управляемого типа данных — объектов класса Man, в условиях управляемого
кода.
void main ()
{
//=== Создаем двухмерный массив указателей
//=== на объекты
класса Man
Man * men[,]
= new Man *[2, 2];
//=== Как вам
нравится новый (управляемый) синтаксис?
//=== Инициализируем один элемент массива
men [1,1] = new
ManC'Alex Black ",54);
//===Мы можем задавать вопросы объекту men
Console: :WriteLine (men->Count) ;
Console: :WriteLine
(men->Rank) ;
Console: :WriteLine (men[l, 1] ->GetName ( ) ) ;
Console: :WriteLine (men [1, 1] ->GetAge () ) ;
}
Программа
выведет следующий текст:
4
2
Alex Black
54
Пока мы видим
только новый синтаксис и возможность задавать вопросы динамическому массиву.
Но теперь попробуйте вставить код с ошибками алгоритмического плана и запустите
на выполнение.
for (int i=0; i<5; i++)
Console::WriteLine(men[i,i]->GetName());
Если вы на
предложение отладить код ответите отказом, то в окне будет выведен такой текст:
Exception
occurred: System.NullReferenceException: Attempted to dereference a null object
reference.
at Man.GetName() in с:\man\man.cpp:line 27
at main() in
с:\man\man.cpp:line 61
Такое поведение
программы в ситуации с типичной ошибкой разработчика, безусловно, следует признать
более надежным. Оно даст возможность значительно сэкономить наше время в будущем.
Отметьте, что если вы не хотите пользоваться услугами автоматического сборщика
мусора (_gс), то не должны делать особое заявление по этому поводу.
Видимо, диск
можно было бы продолжить в том же духе и стиле, который был принят в предыдущем
параграфе, но, к сожалению, время для этого еще не пришло. Во-первых, новые
технологии требуют осмысления, во-вторых, бета-версия Studio.Net работает недостаточно
надежно, в-третьих, документация по новым технологиям ограничена и доступна,
пожалуй, только на сайте Microsoft. Поэтому мы постараемся осветить только ту
часть возможностей, предоставляемых новой версией Studio.Net, которая относится
к разработке настольных (desktop) приложений с использованием Visual C++ 7.0.
Указанную область нельзя назвать узкой, так как она объединяет достаточно большое
количество типов разрабатываемых приложений:
Вы узнаете, как управлять координатными пространствами Windows, как осуществлять взаимодействие нескольких представлений одного документа, как добиваться эффективности и реалистичности изображений OpenGL, как использовать
Shell API для управления файловым деревом, как разрабатывать СОМ-серверы и СОМ-контейнеры, как синхронизировать множество элементов управления в рамках диалога, как создавать свои собственные нестандартные окна, как использовать контейнеры и алгоритмы стандартной библиотеки C++ (STL), как строить графики функций в трехмерном пространстве и, наконец, как решать простейшие краевые задачи с демонстрацией результатов в виде аккуратных графиков. Кроме того, в последней главе вы найдете информацию об архитектуре Windows, с точки зрения разработчика программного обеспечения.
При изложении материала я не стараюсь подробно рассматривать все технические детали использования какого-либо класса, функции или типа данных, так как, на мой взгляд, нецелесообразно ставить себе задачу запоминать детали. Во-первых, их очень много даже в рамках одной технологии, во-вторых, MSDN (Microsoft Developer Network) для того и существует, чтобы при необходимости быстро прийти на помощь, в-третьих, я верю в принцип: чем чаще используете, тем вероятней, что запомните. Вместо этого ставится задача показать, какие преимущества вы получаете, используя новую сущность или новый технологический прием, а главное, как их использовать.
Иногда, я все-таки пускаюсь в пространные описания очень мелких и, казалось бы, непринципиальных деталей, но это делается обычно только после того, как сам потратил в логической ловушке много времени и нервов, ища из нее выход. Жизнь программиста полна ловушек, которые обычно он сам себе и расставляет, что-то недоговаривая, оставляя на потом или просто проявляя лень. Здесь вспоминается поговорка, которую любил повторять на лекциях по математике профессор И. С. Серебрянский в Санкт-Петербургском Политехническом институте: «Математики — это умные лентяи». Думаю, что многие программисты тоже болеют этим недугом, что позволяет им создавать эффективные, краткие, изящные алгоритмы и программы.
Язык C++ служит благодатной почвой для произрастания нестандартных, сложных, порой замысловатых, логических конструкций и неожиданных решений. Новые технологии разработки приложений, а также категории API-функций, довольно проворно разрабатываемые компанией Microsoft, дают пищу фантазии программиста и делают его жизнь еще более беспокойной, разнообразной и от этого более интересной.