Управляемые расширения для C++
Управляемые расширения для C++ или Managed C++ — это устаревший набор языковых расширений для C++ , включая грамматические и синтаксические расширения, ключевые слова и атрибуты, позволяющие перенести синтаксис и язык C++ в .NET Framework . Эти расширения были созданы Microsoft, чтобы позволить коду C++ быть ориентированным на среду Common Language Runtime (CLR) в форме управляемого кода , а также продолжать взаимодействовать с собственным кодом.
В 2004 году расширения Managed C++ были существенно переработаны, чтобы прояснить и упростить синтаксис, а также расширить функциональные возможности за счет включения управляемых универсальных шаблонов . Эти новые расширения получили обозначение C++/CLI и были включены в Microsoft Visual Studio 2005 . [ 1 ] Таким образом, термин Managed C++ и расширения, на которые он ссылается, устарели и заменены новыми расширениями.
История
[ редактировать ]Microsoft представила управляемые расширения для C++ в Microsoft Visual C++ 2002 (MSVC++). Microsoft попыталась свести к минимуму различия между стандартом C++ и управляемыми расширениями для C++, в результате чего основные различия между ними были синтаксически скрыты. MSVC++ 2003 и 2005 также обеспечивала поддержку написания программ на управляемом C++. В 2004 году управляемые расширения для C++ были признаны устаревшими в пользу C++/CLI — второй попытки Microsoft поддержать программирование для Common Language Infrastructure с использованием C++. [ 2 ]
Дизайн
[ редактировать ]Управляемый — это управляемый код , который запускается или управляется .NET виртуальной машиной , которая функционирует как изолированная программная среда для повышения безопасности в виде дополнительных проверок во время выполнения, таких как проверки переполнения буфера. Кроме того, приложения, написанные на управляемом C++, компилируются в CIL (Common Intermediate Language), а не непосредственно в собственные инструкции ЦП , как это делают стандартные приложения C++.
Управляемый код C++ может взаимодействовать с любым другим языком, также предназначенным для CLR, например C# и Visual Basic .NET , а также использовать функции, предоставляемые CLR, такие как сборка мусора . Это означает, что управляемый C++ занимает уникальное место в галерее языков .NET. Это единственный язык, который может напрямую взаимодействовать с языками .NET (такими как C#, VB.NET), а также с собственным C++. Другие языки .NET могут взаимодействовать с кодом C++ только через PInvoke или COM . Но поскольку управляемый C++ может взаимодействовать напрямую как в управляемом, так и в стандартном контекстах C++, его часто используют в качестве «моста».
Функциональность
[ редактировать ]Программы, написанные на Managed C++, предоставляют дополнительные функциональные возможности .NET Framework и CLR . Наиболее примечательным из них является сбор мусора , который освобождает программиста от ручного управления памятью. Сборщиком мусора (GC) управляет среда CLR. Управление памятью выполняется довольно быстро, но для более критичных к производительности приложений, скорее всего, предпочтительным вариантом будет собственный неуправляемый код.
Управляемый C++ ориентирован на объектно-ориентированное программирование. Основное различие между стандартным C++ и управляемым C++ заключается в том, что множественное наследование не поддерживается, а класс, управляемый сборщиком мусора CLR, не может наследовать более одного класса. Это связано с ограничениями CLR.
Ключевые особенности:
- Расширяемые метаданные: информация, предоставляемая для описания структуры и типов управляемого компонента. Его можно расширять и повторно использовать для создания программных компонентов. Он широко используется в C# и Visual Basic .NET.
- Сбор мусора: CLR полностью управляется сборщиком мусора для управления памятью, автоматизированного самой CLR, т. е. оператор удаления не требуется вызывать в управляемом коде C++.
- Взаимодействие с языками .NET: код, предназначенный для .NET Framework, создает выходные данные Microsoft Intermediate Language (MSIL, аналогичный байт-коду Java), и, таким образом, скомпилированные модули и компоненты (скорее сборки) могут повторно использоваться другими программными компонентами, написанными на другом языке, предназначенном для .NET Framework, например JScript .NET, C#, Visual Basic .NET и другие сторонние языки для .NET.
- Управление версиями: новые методы и элементы данных можно добавлять в существующие управляемые классы без нарушения двоичной совместимости с существующим клиентским программным обеспечением.
- Двоичные заголовки: позволяют повторно использовать предварительно скомпилированные метаданные; на любой модуль .exe, .dll, .obj или .net, скомпилированный в MSIL, можно ссылаться из исходного файла C++.
- Защита от переполнения буфера — с появлением в C++ сборки мусора управляемый C++ стал менее подвержен распространенным ошибкам переполнения буфера , вызванным отсутствием проверки типов данных в стандартном C++. Сборщик мусора помогает снизить (хотя и не полностью) частоту этих ошибок.
- .NET Framework Библиотека базовых классов . Управляемый C++ также потенциально может быть менее многословным, чем стандартный неуправляемый код, поскольку все вызовы управляемых функций и унаследованные классы являются производными от библиотеки базовых классов .NET Framework (BCL, иногда называемой FCL или Framework). Библиотека классов), API которой обеспечивает сетевые возможности TCP/IP, функции текстового манипулирования, доступ к данным (от ODBC до SQL), службы XML (от XSD до XSL), программирование графического пользовательского интерфейса (Windows Forms), почтовые службы. (SMTP), криптография (сертификаты X509 и цифровые подписи XML), генерация MSIL (по сути, выдача инструкций в MSIL), файловый ввод-вывод, ручное манипулирование сборщиком мусора CLR и управляющей информацией для управления консолью WMI.
Преимущества перед нативным кодом
[ редактировать ]- Управляемый и неуправляемый код можно легко смешивать в одной сборке CLI . Это позволяет программисту сохранять неуправляемый код, который невозможно перенести на .NET Framework без его полной переписывания. Однако существуют некоторые последствия использования этого гибридного соглашения.
- Управляемый C++ — единственный язык, который может содержать неуправляемый код и напрямую взаимодействовать со всеми другими языками .NET. Таким образом, управляемый C++ очень удобен для взаимодействия между программистами, использующими разные языки, в том числе программистами .NET-театра и теми, кто использует стандартный C++.
Недостатки по сравнению с неуправляемым кодом
[ редактировать ]- Управляемый C++ вводит множество новых ключевых слов и синтаксических соглашений, которые могут ухудшить читаемость кода, особенно если код C++ включен напрямую и напрямую взаимодействует с кодом Managed C++ в той же сборке.
- Управляемый C++ заменяется C++/CLI и, таким образом, устарел, поскольку C++/CLI был стандартизирован.
Недостатки по сравнению с полностью управляемым кодом
[ редактировать ]- Управляемый C++ требует немного большего времени разработки, чем другие языки .NET, которые можно применять к проектам, которые по-прежнему дают те же результаты. Использование указателей может быть обязательным, а может и не быть обязательным, поскольку управляемый C++ имеет как типы значений (структура __value и класс __value), так и ссылочные типы (структура __gc и класс __gc).
- Управляемый C++ полностью поддерживает веб-приложения ASP.NET , хотя разработка более сложна, чем с другими языками .NET, включая некоторые языки сторонних производителей.
- Управляемый C++ включает только поддержку шаблонов (для совместимости с собственным C++), но не поддерживает универсальные шаблоны (для совместимости со всеми другими языками .NET). C++/CLI поддерживает как шаблоны (во время компиляции), так и дженерики (во время выполнения).
Примеры
[ редактировать ]В следующих примерах показано использование управляемого C++ по сравнению со стандартным C++:
- (Глобальное изменение) Существующий C++ для переноса через CLR должен быть дополнен следующим:
//hello.cpp
//new using directive
#using <mscorlib.dll>
//another using namespace directive.
using namespace System;
int main()
{
Console::WriteLine("Hello, world!");
return 0;
}
Новая директива препроцессора
#using <mscorlib.dll>
требуется. В дополнение к этому, для импорта большего количества библиотек и использования большего количества пространств имен в библиотеке базовых классов требуется больше директив #using, например:
#using <System.Windows.Forms.dll>
и
using namespace System::Windows::Forms;
использовать Windows Forms.
- Чтобы скомпилировать код для CLR, необходимо ввести новую опцию компилятора.
cl.exe hello.cpp /clr
/clr позволяет скомпилировать любой код, ссылающийся на .NET Framework, как CIL .
- Класс может быть назначен для сбора мусора с помощью
__gc
Ключевое слово расширения.
//gc.cpp
#using <mscorlib.dll>
__gc class gc
{
int* i;
char* g;
float* j;
};
int main()
{
while (true)
{
gc^ _gc = gcnew gc();
}
return 0;
}
Приведенный выше код можно скомпилировать и выполнить, не опасаясь утечек памяти . Потому что класс gc
управляется сборщиком мусора, нет необходимости вызывать delete
оператор. Чтобы добиться того же с неуправляемым кодом, delete
требуется ключевое слово:
//nogc.cpp
class gc
{
int* i;
char* g;
float* j;
};
int main()
{
while (true)
{
gc* _gc = new gc();
delete _gc;
}
return 0;
}
Примечания:
- Класс, назначенный __gc, может иметь объявленный конструктор.
- Класс, обозначенный __gc, может иметь объявленный деструктор.
- Класс, назначенный __gc, не может наследовать более одного класса. (Это ограничение CLR)
- Класс, назначенный __gc, не может наследовать другой класс, не назначенный __gc.
- Класс, обозначенный __gc, не может быть унаследован другим классом, не обозначенным __gc.
- Класс, назначенный __gc, может реализовывать любое количество интерфейсов __gc.
- Класс, назначенный __gc, не может реализовать неуправляемый интерфейс.
- Класс, назначенный __gc, по умолчанию не виден за пределами собственной сборки. Использовать
public __gc class hey { };
ключевое слово public для изменения доступа к назначенному классу __gc.
Класс, назначенный __gc, можно уничтожить вручную с помощью ключевого слова delete, но только если класс, назначенный __gc, имеет определяемый пользователем деструктор.
- Интерфейс может быть объявлен с предшествующим ему ключевым словом расширения __gc. Такой как:
//interface.cpp
#using <mscorlib.dll>
__gc __interface ClassBase
{
void Init();
int Common();
}
Приведенный выше код необходимо скомпилировать с параметрами /clr и /LD, чтобы создать простой файл DLL.
Примечания:
- __gc __interface не может содержать никаких членов данных, статических членов, объявлений вложенных классов и спецификаторов доступа.
- __gc __interface может наследовать только от другого интерфейса __gc __interface или System::Object. Наследование от System::Object является поведением по умолчанию.
- __gc __interface не может содержать какую-либо реализацию (основной код) своих объявленных прототипов функций.
Сравнение с другими языками
[ редактировать ]Ниже приведены основные моменты и программные стандарты, которые различаются между Managed C++ и другими хорошо известными языками программирования, схожими по концепции.
Стандартный С++
[ редактировать ]Недостатки
- Собственный код C++ может работать быстрее во время выполнения.
- C++ не требует установки соответствующего компилятора и управляемой среды выполнения в целевой системе.
- C++ поддерживает обобщенное программирование . Однако до окончательного выпуска C++/CLI программисты Managed C++ должны вернуться к обходным путям использования универсальных шаблонов.
- C++ поддерживает ключевое слово const и константную корректность . Управляемый C++, как Java и C#, не содержит этой функции. Альтернативой является сделать управляемый класс неизменяемым или ограничить доступ к набору средств доступа на общедоступных интерфейсах.
- Код C++ не ограничен ограничениями CLR. Например, CLR не позволяет классам наследовать другие классы конфиденциально или защищенно, поэтому следующая ошибка компилятора приведет к ошибке:
public __gc class one { int i; };
public __gc class two: private one { int h; i = h; }; // error
public __gc class three: protected one { int h; i=h;}; // error
- Управляемые классы C++ __gc не могут наследовать более чем от одного класса, поэтому следующее приведет к ошибке компилятора:
__gc class a {};
__gc class b {};
__gc class c: public a, public b {}; //will produce an error
Преимущества
- Управляемый C++ поддерживает более высокую степень отражения , чем обычный C++, что обычно намного удобнее в зависимости от функции кода или того, для чего он предназначен.
- Управляемый C++ может взаимодействовать со всеми другими языками, поддерживающими .NET, включая языки сторонних производителей.
- Управляемый C++ предназначен для сбора мусора. В стандарте C++ ответственность за управление и распределение памяти лежит на программисте.
Ява
[ редактировать ]Различия
- Для запуска кода Java требуется соответствующая виртуальная машина, а для запуска управляемого кода C++ требуется соответствующая реализация .NET Framework.
Недостатки
- Java предоставляет документацию по исходному коду, а Managed C++ — нет.
- Java имеет множество других инструментов разработки, доступных для использования Java-программистами, тогда как Managed C++ доступен только в Visual Studio .NET .
Преимущества
- Управляемый C++ обеспечивает гораздо более простой доступ к компьютерной системе через низкоуровневый интерфейс, чем Java. Программисты Java должны использовать JNI (Java Native Interface) для использования низкоуровневых сервисов операционной системы хоста.
С#
[ редактировать ]Различия
- Хотя C# поддерживает указатели, как и C++, по умолчанию эта функция отключена.
Недостатки
- Как и Java , C# синтаксически проще при работе с управляемым кодом.
- C# позволяет достичь в основном того же результата, что и Managed C++, поскольку все синтаксические и структурные соглашения остаются поразительно схожими.
- Управляемый C++, хотя это строго типизированный язык из-за его введения в CLR, может быть подвержен ошибкам, если неуправляемый скомпилированный код вводится в ту же базу кода, в то время как C# является чистым MSIL.
Преимущества
- C# должен использовать .NET Framework и предоставленные библиотеки классов для доступа к компьютерной системе на низком уровне.
- Переносить приложения на .NET Framework с C или C++ гораздо проще, используя Managed C++.
- Компилятор Microsoft Visual C++ .NET, который компилирует Managed C++ для .NET Framework, создает в результирующей сборке гораздо более продуманный набор инструкций, тем самым повышая производительность.
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ «Руководство по переводу: перенос ваших программ из управляемых расширений для C++ в C++/CLI» . Майкрософт . Август 2004 года . Проверено 11 ноября 2009 г.
- ^ Саттер, Херб. «Обоснование проектирования C/C++» (PDF) . п. 6. Архивировано (PDF) из оригинала 30 августа 2017 г. Проверено 12 июня 2018 г.