C++/CLI

C++/CLI
パラダイム構造化命令型オブジェクト指向
家族C
デザイン:マイクロソフト
開発者マイクロソフト
初登場2005 (2005年
プラットフォーム共通言語インフラストラクチャ
Webサイトdocs .microsoft .com /en-us /cpp /dotnet /dotnet-programming-with-cpp-cli-visual-cpp
影響を受けた
C++C++ のマネージ拡張C#

C++/CLIは、 C++プログラミング言語の派生であり、共通言語基盤(Common Language Infrastructure)向けに改良されています。Visual Studio 2005以降に搭載されており、 C#などの他の.NET言語との相互運用性を提供しています。Microsoftは、C++のマネージド拡張機能(Managed Extensions for C++)に代わるものとしてC++/CLIを開発しました。2005年12月、Ecma InternationalはC++/CLI仕様をECMA-372標準として公開しました。[ 1 ]

構文の変更

C++/CLIは、C++のスーパーセット指向のManaged C++ (MC++)(非標準キーワードは または のようなスタイルで表記されていました)ではなく、独自の言語(例えば、新しいキーワードセットを持つ__gc)として考える__valueべきです。そのため、曖昧な識別子の排除や.NET固有の機能の追加など、いくつかの大きな構文変更が行われています。

MC++の演算子の複数のバージョンなど、多くの矛盾する構文が分割されました。C++/CLIでは、.NET参照型はnewキーワード(つまり、ガベージコレクションされたnew())で作成されます。また、C++/CLIは.NETからジェネリックの概念を導入しました(一般的な用途では標準C++テンプレートに似ていますが、実装は大きく異なります)。 new()gcnew

C++/CLI ではarray<T>ネイティブ C# 配列を参照するためにを使用しT[]、C# では System::Array<T>ラッパー クラスを参照するために を使用します。System.Array<T>

ハンドル

MC++では、ポインタには2種類ありました。__nogcポインタは通常のC++ポインタで、__gcポインタは.NET参照型で使用されていました。しかし、C++/CLIでは、ポインタは通常のC++ポインタのみで、.NET参照型には新しい構文( ではなく)の「ハンドル」を介してアクセスします。この新しい構文は、マネージドコードと標準C++コードが混在している場合に特に役立ちます。これにより、.NETの自動ガベージコレクションの対象となるオブジェクトと、プログラマが明示的に破棄する必要があるオブジェクトが明確になります。 ClassName^ClassName*

参照の追跡

C++/CLIにおける追跡参照は、参照渡しされる変数のハンドルです。これは、*&標準C++におけるポインタへの参照の使用(using)と概念的に似ており、関数宣言においてはC#またはVisual Basic .NETにおけるref型に適用されるキーワードに相当します。C++/CLIでは、ハンドルへの追跡参照を示す構文 を使用します。ByRef^%

以下のコードは、追跡参照の使用例を示しています。追跡参照を通常のハンドル変数に置き換えると、結果の文字列配列には10個の初期化されていない文字列ハンドルが残ります。これは、文字列ハンドルが参照ではなく値渡しされるため、配列内の文字列ハンドルのコピーのみが設定されるためです。

int main () {配列<文字列^>^ arr = gcnew配列<文字列^> ( 10 ); int i = 0 ;for each ( String ^% s in arr ) { s = i ++ . ToString (); }0を返す; }

ファイナライザと自動変数

C++/CLI におけるもう一つの変更点は、ファイナライザ構文の導入です。これは、ガベージコレクションルーチンの一部として実行される特殊な非決定的デストラクタです。C++ のデストラクタ構文はマネージドオブジェクトにも存在し、決定的デストラクション(つまり、ユーザーコードから を使って呼び出せるデストラクタ)の「伝統的な」C++ セマンティクスをより適切に反映しています。 !ClassName()~ClassName()delete

Finalize生の.NETパラダイムでは、非決定的な破棄モデルはルートクラスの保護メソッドをオーバーライドしますObjectが、決定的なモデルはIDisposableインターフェースメソッドDispose(C++/CLIコンパイラによってデストラクタに変換される)を通じて実装されます。C#またはVB.NETコードでDisposeメソッドをオーバーライドするオブジェクトは、C++/CLIdeleteの.NETクラスと同様に、C++/CLIで手動で破棄できます。

// C++/CLI ref class MyClass { protected : ! MyClass (); // ファイナライザー (非決定論的デストラクタ) (Finalize() として実装) public : MyClass (); // コンストラクター~ MyClass (); // (決定論的) デストラクタ (IDisposable.Dispose() として実装) static void Test () { MyClass automatic ; // ハンドルではなく、初期化なし: コンパイラはここでコンストラクターを呼び出しますMyClass ^ user = gcnew MyClass (); delete user ;// コンパイラは automatic がスコープ外になると automatic のデストラクタを呼び出します} };

演算子のオーバーロード

演算子オーバーロードは標準C++と同様に動作します。すべての*は になり ^、すべての&は になります%が、その他の構文は重要な追加を除いて変更ありません。.NETクラスの場合、演算子オーバーロードはクラス自体だけでなく、それらのクラスへの参照に対しても可能です。この機能は、refクラスに、.NET refクラスに期待される演算子オーバーロードのセマンティクスを与えるために必要です。(逆に言えば、.NETフレームワークのrefクラスの場合、参照演算子オーバーロードはC++/CLIで暗黙的に実装されていることが多いことを意味します。)

例えば、2つの異なる文字列参照 ( String^) を 演算子 で比較すると==、2つの文字列が等しい場合は常に true が返されます。ただし、演​​算子のオーバーロードは静的です。したがって、 にキャストするとObject^オーバーロードのセマンティクスは削除されます。

//参照演算子オーバーロードの効果String ^ s1 = "abc" ; String ^ s2 = "ab" + "c" ; Object ^ o1 = s1 ; Object ^ o2 = s2 ; s1 == s2 ; // true o1 == o2 ; // false

相互運用性

C++/CLIを使用すると、C++プログラムからC# DLL内のC#プログラムを使用できます。[ 2 ] ここで、キーワードはコンパイラに、コンパイルメタデータを格納するDLLの場所を示します。この単純な例では、データマーシャリングは#using必要ありません。

#include "stdafx.h" #using "...MyCS.dll"名前空間Systemを使用しますint main (配列< String ^>^ args ) { double x = MyCS :: Class1 :: add ( 40.1 , 1.9 ); 0を返します; }

MyCS.dll の C# ソース コードの内容。

名前空間MyCS ;パブリッククラスClass1 {パブリック静的double add ( double a double b ) {戻り値a + b ; } }

この例では、C++ 文字列を C# から呼び出し可能な文字列に変換し、さらに C++ 文字列に戻す方法を示します。文字列のマーシャリングでは、文字列の内容をさまざまな環境で使用可能な形式にコピーします。

#include <文字列> #include <iostream> #include <msclr\marshal_cppstd.h> #include "stdafx.h" #using "..MyCS.dll"名前空間Systemを使用しますint main () { std :: string s = "I am cat" ; String ^ clrString = msclr :: interop :: marshal_as < String ^> ( s ); // C# から使用可能な文字列 (System::String) String ^ t = MyCS :: Class1 :: process ( clrString ); // C# 関数を呼び出すstd :: string cppString = msclr :: interop :: marshal_as < std :: string > ( t ); // C++ から使用可能な文字列std :: cout << "Hello, C++/C# Interop!" << std :: endl ; std :: cout << cppString << std :: endl ; return 0 ; }

C# コードは C++ に対応していません。

名前空間MyCS ;public class Class1 { public static string process ( string a ) { return a . Replace ( "cat" , "dog" ) + " with a tail" ; } }

C++/C# の相互運用性により、C++ から .NET 機能の世界全体に簡単にアクセスできるようになります。

C++/CX

WinRTをターゲットとしたC++/CXは、完全にアンマネージなコードを生成しますが、COM 「オブジェクト」に似たWinRTの参照カウントコンポーネントのrefと構文を借用しています。[ 3 ]^

参考文献

さらに読む