ユーザー定義変換 (C++/CLI)

このセクションでは、変換の型の 1 つが値の型または参照型の参照またはインスタンスである場合のユーザー定義変換 (UDC) について説明します。

暗黙的な型変換と明示的な型変換

ユーザー定義変換には、暗黙的または明示的な変換を使用できます。 変換によって情報の損失が生じない場合、UDC は暗黙的である必要があります。 それ以外の場合は、明示的な UDC を定義する必要があります。

ネイティブ クラスのコンストラクターを使用して、参照型または値の型をネイティブ クラスに変換できます。

変換の詳細については、ボックス化に関する記事および「標準変換」を参照してください。

// mcpp_User_Defined_Conversions.cpp
// compile with: /clr
#include "stdio.h"
ref class R;
class N;

value class V {
   static operator V(R^) {
      return V();
   }
};

ref class R {
public:
   static operator N(R^);
   static operator V(R^) {
      System::Console::WriteLine("in R::operator N");
      return V();
   }
};

class N {
public:
   N(R^) {
      printf("in N::N\n");
   }
};

R::operator N(R^) {
   System::Console::WriteLine("in R::operator N");
   return N(nullptr);
}

int main() {
   // Direct initialization:
   R ^r2;
   N n2(r2);   // direct initialization, calls constructor
   static_cast<N>(r2);   // also direct initialization

   R ^r3;
   // ambiguous V::operator V(R^) and R::operator V(R^)
   // static_cast<V>(r3);
}

出力

in N::N
in N::N

変換元演算子

変換元演算子は、演算子が他のクラスのオブジェクトから定義されているクラスのオブジェクトを作成します。

標準 C++ では、変換元演算子はサポートされていません。標準 C++ では、この目的のためにコンストラクターが使用されます。 ただし、CLR 型を使用する場合、Visual C++ では変換元演算子を呼び出すための構文サポートが提供されます。

他の CLS 準拠言語と適切に相互運用するには、特定のクラスのユーザー定義の各単項コンストラクターを、対応する変換元演算子でラップすることができます。

変換元演算子:

  • 静的関数として定義する必要があります。

  • 暗黙的 (short-to-int のような精度が失われない変換の場合)、または精度が失われる可能性がある場合は、明示的のどちらかにすることができます。

  • 含まれているクラスのオブジェクトを返す必要があります。

  • 唯一のパラメーター型として "from" 型を指定する必要があります。

次の例は、暗黙的および明示的なユーザー定義変換 (UDC) の "変換元" 演算子を示しています。

// clr_udc_convert_from.cpp
// compile with: /clr
value struct MyDouble {
   double d;

   MyDouble(int i) {
      d = static_cast<double>(i);
      System::Console::WriteLine("in constructor");
   }

   // Wrap the constructor with a convert-from operator.
   // implicit UDC because conversion cannot lose precision
   static operator MyDouble (int i) {
      System::Console::WriteLine("in operator");
      // call the constructor
      MyDouble d(i);
      return d;
   }

   // an explicit user-defined conversion operator
   static explicit operator signed short int (MyDouble) {
      return 1;
   }
};

int main() {
   int i = 10;
   MyDouble md = i;
   System::Console::WriteLine(md.d);

   // using explicit user-defined conversion operator requires a cast
   unsigned short int j = static_cast<unsigned short int>(md);
   System::Console::WriteLine(j);
}

出力

in operator
in constructor
10
1

変換先演算子

変換先演算子は、演算子が定義されているクラスのオブジェクトを他のオブジェクトに変換します。 次の例は、暗黙的なユーザー定義変換の変換先演算子を示しています。

// clr_udc_convert_to.cpp
// compile with: /clr
using namespace System;
value struct MyInt {
   Int32 i;

   // convert MyInt to String^
   static operator String^ ( MyInt val ) {
      return val.i.ToString();
   }

   MyInt(int _i) : i(_i) {}
};

int main() {
   MyInt mi(10);
   String ^s = mi;
   Console::WriteLine(s);
}

出力

10

明示的なユーザー定義の変換先変換演算子は、何らかの方法でデータが失われる可能性がある変換に適しています。 明示的な変換先演算子を呼び出す場合は、キャストを使用する必要があります。

// clr_udc_convert_to_2.cpp
// compile with: /clr
value struct MyDouble {
   double d;
   // convert MyDouble to Int32
   static explicit operator System::Int32 ( MyDouble val ) {
      return (int)val.d;
   }
};

int main() {
   MyDouble d;
   d.d = 10.3;
   System::Console::WriteLine(d.d);
   int i = 0;
   i = static_cast<int>(d);
   System::Console::WriteLine(i);
}

出力

10.3
10

ジェネリック クラスを変換する方法

ジェネリック クラスを T に変換できます。

// clr_udc_generics.cpp
// compile with: /clr
generic<class T>
public value struct V {
   T mem;
   static operator T(V v) {
      return v.mem;
   }

   void f(T t) {
      mem = t;
   }
};

int main() {
   V<int> v;
   v.f(42);
   int i = v;
   i += v;
   System::Console::WriteLine(i == (42 * 2) );
}

出力

True

変換コンストラクターは型を受け取り、それを使用してオブジェクトを作成します。 変換コンストラクターは、直接の初期化でのみ呼び出されます。キャストでは、変換コンストラクターは呼び出されません。 既定では、コンストラクターの変換は CLR 型に対して明示的です。

// clr_udc_converting_constructors.cpp
// compile with: /clr
public ref struct R {
   int m;
   char c;

   R(int i) : m(i) { }
   R(char j) : c(j) { }
};

public value struct V {
   R^ ptr;
   int m;

   V(R^ r) : ptr(r) { }
   V(int i) : m(i) { }
};

int main() {
   R^ r = gcnew R(5);

   System::Console::WriteLine( V(5).m);
   System::Console::WriteLine( V(r).ptr);
}

出力

5
R

このコード サンプルでは、暗黙的な静的変換関数は、明示的な変換コンストラクターと同じ処理を行います。

public value struct V {
   int m;
   V(int i) : m(i) {}
   static operator V(int i) {
      V v(i*100);
      return v;
   }
};

public ref struct R {
   int m;
   R(int i) : m(i) {}
   static operator R^(int i) {
      return gcnew R(i*100);
   }
};

int main() {
   V v(13);   // explicit
   R^ r = gcnew R(12);   // explicit

   System::Console::WriteLine(v.m);
   System::Console::WriteLine(r->m);

   // explicit ctor can't be called here: not ambiguous
   v = 5;
   r = 20;

   System::Console::WriteLine(v.m);
   System::Console::WriteLine(r->m);
}

出力

13
12
500
2000

関連項目

クラスと構造体