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 Tinju 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 Convert-From

Operator convert-from membuat objek kelas tempat operator didefinisikan dari objek dari beberapa 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 convert-from:

  • 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.

  • Harus mengembalikan objek dari kelas yang berisi.

  • Harus memiliki jenis "dari" sebagai jenis parameter satu-satu.

Sampel berikut menunjukkan operator implisit dan eksplisit "convert-from", konversi yang ditentukan 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 kelas tempat operator didefinisikan ke beberapa objek lain. Sampel berikut menunjukkan operator konversi implisit, konversi ke 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 ke konversi eksplisit yang ditentukan pengguna sesuai untuk konversi yang berpotensi 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 yang mengonversi mengambil jenis 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

Baca juga

Kelas dan Struktur