С++/CLI
этой статьи Начальный раздел может быть слишком коротким, чтобы адекватно суммировать ключевые моменты . ( март 2015 г. ) |
Парадигма | Структурированный , императивный , объектно-ориентированный |
---|---|
Семья | С |
Разработано | Майкрософт |
Разработчик | Майкрософт |
Впервые появился | 2005 г |
Платформа | Общая языковая инфраструктура |
Веб-сайт | документы |
Под влиянием | |
C++ , Управляемые расширения для C++ , C# |
C++/CLI — это вариант C++ языка программирования , модифицированный для Common Language Infrastructure . Он был частью Visual Studio 2005 и более поздних версий и обеспечивает совместимость с другими языками .NET, такими как C# . Microsoft создала C++/CLI, чтобы заменить управляемые расширения для C++ . В декабре 2005 года Ecma International опубликовала спецификации C++/CLI как стандарт ECMA-372 . [1]
Изменения синтаксиса
[ редактировать ]C++/CLI следует рассматривать как отдельный язык (например, с новым набором ключевых слов), а не как управляемый C++, ориентированный на надмножество C++ (MC++) (чьи нестандартные ключевые слова были стилизованы как __gc
или __value
). По этой причине произошли некоторые серьезные синтаксические изменения, особенно связанные с устранением неоднозначных идентификаторов и добавлением функций, специфичных для .NET.
Множество конфликтующих синтаксисов, например, несколько версий оператора new()
в MC++ разделены: в C++/CLI ссылочные типы .NET создаются с помощью нового ключевого слова gcnew
(т.е. сбор мусора new()). Кроме того, в C++/CLI введена концепция обобщений из .NET (для наиболее распространенных целей аналогичных стандартным шаблонам C++, но совершенно отличающихся по своей реализации).
Ручки
[ редактировать ]В MC++ существовало два разных типа указателей : __nogc
указатели были обычными указателями C++, а __gc
указатели работали с ссылочными типами .NET. Однако в C++/CLI единственным типом указателя является обычный указатель C++, тогда как доступ к ссылочным типам .NET осуществляется через «дескриптор» с новым синтаксисом. ClassName^
(вместо ClassName*
). Эта новая конструкция особенно полезна при смешивании управляемого и стандартного кода C++; он уточняет, какие объекты подлежат автоматической сборке мусора .NET, а какие объекты программист должен не забыть явно уничтожить.
Отслеживание ссылок
[ редактировать ]Ссылка отслеживания в C++/CLI — это дескриптор переменной, передаваемой по ссылке. По своей концепции это похоже на использование *&
(ссылка на указатель) в стандарте C++ и (в объявлениях функций) соответствует ref
ключевое слово, применяемое к типам в C#, или ByRef
в Visual Basic .NET . C++/CLI использует ^%
синтаксис для указания ссылки отслеживания на дескриптор.
В следующем коде показан пример использования ссылок отслеживания. Замена ссылки отслеживания на обычную переменную-дескриптор оставит в результирующем массиве строк 10 неинициализированных дескрипторов строк, поскольку в массиве будут установлены только копии дескрипторов строк, поскольку они передаются по значению, а не по ссылке.
int main()
{
array<String^> ^arr = gcnew array<String^>(10);
int i = 0;
for each(String^% s in arr) {
s = i++.ToString();
}
return 0;
}
Обратите внимание, что это было бы незаконно в C#, который не позволяет foreach
циклы для передачи значений по ссылке. Следовательно, потребуется обходной путь.
Финализаторы и автоматические переменные
[ редактировать ]Еще одно изменение в C++/CLI — введение финализатора . синтаксиса !ClassName()
, особый тип недетерминированного деструктора, который запускается как часть процедуры сборки мусора . Синтаксис деструктора C++ ~ClassName()
также существует для управляемых объектов и лучше отражает «традиционную» семантику C++ детерминированного разрушения (то есть деструкторы, которые могут вызываться из пользовательского кода с помощью delete
).
В «сырой» парадигме .NET недетерминированная модель уничтожения переопределяет защищенную модель. Finalize
метод корня Object
класс, а детерминированная модель реализуется через IDisposable
интерфейса метод Dispose
(в который компилятор C++/CLI превращает деструктор). Объекты из кода C# или VB.NET, которые переопределяют метод Dispose, можно удалить вручную в C++/CLI с помощью delete
точно так же, как это могут делать классы .NET в C++/CLI.
// C++/CLI
ref class MyClass
{
public:
MyClass(); // constructor
~MyClass(); // (deterministic) destructor (implemented as IDisposable.Dispose())
protected:
!MyClass(); // finalizer (non-deterministic destructor) (implemented as Finalize())
public:
static void Test()
{
MyClass automatic; // Not a handle, no initialization: compiler calls constructor here
MyClass ^user = gcnew MyClass();
delete user;
// Compiler calls automatic's destructor when automatic goes out of scope
}
};
Перегрузка оператора
[ редактировать ]Перегрузка операторов работает аналогично стандартному C++. Каждый * становится ^, каждый & становится %, но остальная часть синтаксиса не меняется, за исключением важного дополнения: для классов .NET перегрузка операторов возможна не только для самих классов, но и для ссылок на эти классы. Эта функция необходима для того, чтобы придать ссылочному классу семантику перегрузки операторов, ожидаемую от ссылочных классов .NET. (Наоборот, это также означает, что для ссылочных классов .NET Framework перегрузка ссылочного оператора часто неявно реализуется в C++/CLI.)
Например, сравнение двух различных ссылок на строки (String^) с помощью оператора == даст значение true, если две строки равны. Однако перегрузка операторов является статической. Таким образом, приведение к Object^ удалит семантику перегрузки.
//effects of reference operator overloading
String ^s1 = "abc";
String ^s2 = "ab" + "c";
Object ^o1 = s1;
Object ^o2 = s2;
s1 == s2; // true
o1 == o2; // false
Совместимость
[ редактировать ]C++/CLI позволяет программам C++ использовать программы C# в библиотеках C# DLL. [2] Здесь ключевое слово #using указывает компилятору, где находится DLL для ее метаданных компиляции. Этот простой пример не требует маршаллинга данных .
#include "stdafx.h"
using namespace System;
#using "...MyCS.dll"
int main(array<System::String ^> ^args) {
double x = MyCS::Class1::add(40.1, 1.9);
return 0;
}
Содержимое исходного кода C# MyCS.dll.
namespace MyCS;
public class Class1 {
public static double add(double a, double b) {
return a + b;
}
}
В этом примере показано, как строки маршалируются из строк C++ в строки, вызываемые из C#, а затем обратно в строки C++. Маршалинг строк копирует содержимое строки в формы, которые можно использовать в различных средах.
#include <string>
#include <iostream>
#include <msclr\marshal_cppstd.h>
#include "stdafx.h"
using namespace System;
#using "..MyCS.dll"
int main() {
std::string s = "I am cat";
System::String^ clrString = msclr::interop::marshal_as<System::String^>(s); // string usable from C#
System::String^ t = MyCS::Class1::process(clrString); // call C# function
std::string cppString = msclr::interop::marshal_as<std::string>(t); // string usable from C++
std::cout << "Hello, C++/C# Interop!" << std::endl;
std::cout << cppString << std::endl;
return 0;
}
Код C# никоим образом не поддерживает C++.
namespace MyCS;
public class Class1 {
public static string process(string a) {
return a.Replace("cat", "dog") + " with a tail";
}
}
Совместимость C++/C# обеспечивает упрощенный доступ C++ ко всему миру функций .NET.
С++/CX
[ редактировать ]C++/CX, ориентированный на WinRT , хотя и создает полностью неуправляемый код, заимствует синтаксис ref и ^ для компонентов WinRT с подсчетом ссылок, которые похожи на COM . «объекты» [3]
Ссылки
[ редактировать ]- ^ «ЭКМА-372» . ecma-international.org . Экма Интернешнл . Декабрь 2005 г. Архивировано из оригинала 10 августа 2008 г.
- ^ Использование взаимодействия с C++ (неявный PInvoke)
- ^ Внутри C++/CX Design — Блог группы Visual C++ — Домашняя страница сайта — Блоги MSDN
Дальнейшее чтение
[ редактировать ]- Саттер, Херб (23 ноября 2003 г.). «Ключевые слова C++/CLI: под капотом» . Блог Херба Саттера . Майкрософт . Архивировано из оригинала 9 ноября 2007 года.
- Саттер, Херб (24 февраля 2006 г.). «Обоснование дизайна C++/CLI» (PDF) . Самостоятельно опубликовано .
- Страуструп, Бьярне (23 июля 2021 г.). «Что вы думаете о C++/CLI?» . Часто задаваемые вопросы Бьярна Страуструпа . Самостоятельно опубликовано .
- Липпман, Стэнли . «Чистый C++: Привет, C++/CLI» . Журнал MSDN . 21 (3). Майкрософт . Архивировано из оригинала 5 февраля 2008 года.
- Липпман, Стэнли (5 августа 2004 г.). «Почему C++/CLI поддерживает как шаблоны для типов CLI, так и универсальный механизм CLI» . Блог Стэна Липпмана . Майкрософт . Архивировано из оригинала 7 октября 2007 года.