Megosztás a következőn keresztül:


User-Defined Konverziók (C++/CLI)

Ez a szakasz a felhasználó által definiált konverziókat (UDC) ismerteti, ha az átalakítás egyik típusa egy értéktípus vagy referenciatípus hivatkozása vagy példánya.

Implicit és explicit konverziók

A felhasználó által definiált átalakítás lehet implicit vagy explicit. Az UDC-nek implicitnek kell lennie, ha az átalakítás nem okoz adatvesztést. Ellenkező esetben explicit UDC-t kell definiálni.

A natív osztály konstruktorát használhatja referencia- vagy értéktípus natív osztálysá alakításához.

További információ a konverziókról: Boxing and Standard Conversions.

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

Kimenet

in N::N
in N::N

Convert-From operátorok

A konvertálási operátorok létrehoznak egy objektumot annak az osztálynak, amelyben az operátor egy másik osztály objektumából van definiálva.

A standard C++ nem támogatja a konvertálást operátorokból; A standard C++ erre a célra konstruktorokat használ. CLR-típusok használatakor azonban a Visual C++ szintaktikai támogatást nyújt a konvertálás operátorokból való meghívásához.

A más CLS-megfelelő nyelvekkel való jó együttműködés érdekében érdemes lehet egy adott osztály minden felhasználó által definiált egértényezős konstruktorát egy megfelelő konverziós operátorral körbekeríteni.

Konvertálás operátorokból:

  • Statikus függvényként kell definiálni.

  • Lehet implicit (olyan konverziók esetében, amelyek nem veszítik el a pontosságot, például a rövid-int) vagy explicit, ha a pontosság csökkenhet.

  • A tartalmazó osztály egy objektumát adja vissza.

  • Egyetlen paramétertípusként a "from" típusnak kell rendelkeznie.

Az alábbi minta egy implicit és explicit "convert-from", felhasználó által definiált konverziós (UDC) operátort mutat be.

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

Kimenet

in operator
in constructor
10
1

Átalakítás operátorokká

Az átkonvertálást végző operátorok az objektum osztályában vannak definiálva, és azzal az osztálybeli objektummal más objektumra konvertálják. Az alábbi minta egy implicit, konvertáló, felhasználó által definiált konverziós operátort mutat be:

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

Kimenet

10

Egy explicit, felhasználó által definiált konvertálási operátor olyan konverziókhoz megfelelő, amelyek valamilyen módon esetleg adatvesztést eredményeznek. Az explicit konvertáló operátor meghívásához típuskonverziót kell használni.

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

Kimenet

10.3
10

Általános osztályok konvertálása

Egy generikus osztályt átalakíthat T típusra.

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

Kimenet

True

A konvertáló konstruktorok egy típust használnak, és egy objektum létrehozásához használják. A konvertáló konstruktort csak közvetlen inicializálással hívjuk meg; a típuskényszerítések nem fogják meghívni a konvertáló konstruktorokat. Alapértelmezés szerint a konvertáló konstruktorok explicitek a CLR-típusok esetében.

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

Kimenet

5
R

Ebben a kódmintában egy implicit statikus konverziós függvény ugyanazt teszi, mint egy explicit konverziós konstruktor.

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

Kimenet

13
12
500
2000

Lásd még

Osztályok és struktúrák