Aracılığıyla paylaş


Kullanıcı Tanımlı Dönüşümler (C++/CLI)

Bu bölümde, dönüştürmedeki türlerden biri bir değer türünün veya başvuru türünün başvurusu veya örneği olduğunda kullanıcı tanımlı dönüştürmeler (UDC) ele alınmaktadır.

Örtük ve açık dönüştürmeler

Kullanıcı tanımlı dönüştürme örtük veya açık olabilir. Dönüştürme bilgi kaybına neden olmazsa bir UDC gizli olmalıdır. Aksi takdirde açık bir UDC tanımlanmalıdır.

Bir başvuruyu veya değer türünü yerel sınıfa dönüştürmek için yerel sınıfın oluşturucus kullanılabilir.

Dönüştürmeler hakkında daha fazla bilgi için bkz. Kutulama ve Standart Dönüştürmeler.

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

Çıktı

in N::N
in N::N

Dönüştürme Kaynağı İşleçleri

Başka bir sınıfın nesnesinden, operatörün tanımlandığı sınıfın bir nesnesini oluşturan dönüştürme işleçleri.

Standart C++ dönüştürme işleçlerini desteklemez; standard C++ bu amaç için oluşturucuları kullanır. Ancak, CLR türlerini kullanırken, Visual C++ dönüştürme işleçlerinden olan operatörleri çağırmak için sentaks desteği sağlar.

Diğer CLS uyumlu dillerle iyi bir şekilde birlikte çalışabilmek için, belirli bir sınıf için kullanıcı tanımlı her tekli operatörü, karşılık gelen bir dönüştürme operatörüyle sarmalamanız faydalı olabilir.

Dönüştürme işleçleri:

  • Statik fonksiyonlar olarak tanımlanmalıdır.

  • Dönüştürmeler duyarlık kaybı olmadan yapılabiliyorsa örtük (kısa-int gibi) olabilir veya duyarlık kaybı olasılığı varsa açık olmalıdır.

  • İçeren sınıfın bir nesnesini döndürür.

  • Tek parametre türü olarak "from" türüne sahip olmalıdır.

Aşağıdaki örnekte örtük ve açık bir "dönüştürme", kullanıcı tanımlı dönüştürme (UDC) işleci gösterilmektedir.

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

Çıktı

in operator
in constructor
10
1

Dönüştürme işleçleri

Dönüştürme işleçleri, işlecin tanımlandığı sınıfın bir nesnesini başka bir nesneye dönüştürür. Aşağıdaki örnekte örtük, dönüştürülen, kullanıcı tanımlı dönüştürme işleci gösterilmektedir:

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

Çıktı

10

Açık kullanıcı tanımlı dönüştürme işleci, verileri bir şekilde kaybetme olasılığı olan dönüştürmeler için uygundur. Açık bir dönüştürme işleci çağırmak için bir atama kullanılmalıdır.

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

Çıktı

10.3
10

Genel sınıfları dönüştürmek için

Genel bir sınıfı T'ye dönüştürebilirsiniz.

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

Çıktı

True

Dönüştürücü kurucu bir tür alır ve bunu bir nesne oluşturmak için kullanır. Dönüştüren oluşturucu yalnızca doğrudan başlatma ile çağrılır; o nedenle, tür dönüştürmeleri dönüştüren oluşturucuları çağırmaz. Varsayılan olarak, CLR türleri için dönüştürücü oluşturucular belirgin olarak tanımlıdır.

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

Çıktı

5
R

Bu kod örneğinde örtük statik dönüştürme işlevi, açık dönüştürme oluşturucuyla aynı şeyi yapar.

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

Çıktı

13
12
500
2000

Ayrıca bkz.

Sınıflar ve Yapılar