Bagikan melalui


Konversi yang Ditentukan Pengguna (C++/CLI)

Bagian ini membahas konversi yang ditentukan pengguna (UDC) ketika salah satu jenis dalam konversi adalah referensi atau instans jenis nilai atau jenis referensi.

Konversi implisit dan eksplisit

Konversi yang ditentukan pengguna bisa implisit atau eksplisit. UDC harus implisit jika konversi tidak mengakibatkan hilangnya informasi. Jika tidak, UDC eksplisit harus didefinisikan.

Konstruktor kelas asli dapat digunakan untuk mengonversi referensi atau jenis nilai ke kelas asli.

Untuk informasi selengkapnya tentang konversi, lihat Boxing dan Konversi Standar.

// 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);
}

Hasil

in N::N
in N::N

Operator Dari-Konversi

Operator convert-from membuat objek dari kelas di mana operator tersebut didefinisikan, menggunakan objek dari kelas lain.

C++ standar tidak mendukung operator convert-from; C++ standar menggunakan konstruktor untuk tujuan ini. Namun, saat menggunakan jenis CLR, Visual C++ memberikan dukungan sintik untuk memanggil operator convert-from.

Untuk beroperasi dengan baik dengan bahasa yang sesuai dengan CLS lainnya, Anda mungkin ingin membungkus setiap konstruktor unary yang ditentukan pengguna untuk kelas tertentu dengan operator convert-from yang sesuai.

Operator konversi-dari

  • Harus didefinisikan sebagai fungsi statis.

  • Dapat berupa implisit (untuk konversi yang tidak kehilangan presisi seperti short-to-int) atau eksplisit, ketika mungkin ada hilangnya presisi.

  • Mengembalikan objek dari kelas yang memuat.

  • Harus memiliki tipe "from" sebagai satu-satunya jenis parameter.

Sampel berikut menunjukkan operator konversi implisit dan eksplisit dari, serta operator konversi yang didefinisikan pengguna (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);
}

Hasil

in operator
in constructor
10
1

Mengonversi ke operator

Operator convert-to mengonversi objek dari kelas di mana operator didefinisikan ke objek lainnya. Sampel berikut menunjukkan operator konversi implisit, yang mengkonversikan ke tipe yang ditentukan pengguna:

// 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);
}

Hasil

10

Operator konversi eksplisit yang ditentukan pengguna cocok untuk konversi yang berpotensi menyebabkan kehilangan data dalam beberapa cara. Untuk memanggil operator convert-to eksplisit, cast harus digunakan.

// 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);
}

Hasil

10.3
10

Untuk mengonversi kelas generik

Anda dapat mengonversi kelas generik ke 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) );
}

Hasil

True

Konstruktor konversi mengambil tipe dan menggunakannya untuk membuat objek. Konstruktor konversi hanya dipanggil dengan inisialisasi langsung; cast tidak akan memanggil konstruktor konversi. Secara default, mengonversi konstruktor bersifat eksplisit untuk jenis 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);
}

Hasil

5
R

Dalam sampel kode ini, fungsi konversi statis implisit melakukan hal yang sama dengan konstruktor konversi eksplisit.

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);
}

Hasil

13
12
500
2000

Lihat juga

Kelas dan Struktur