Dela via


User-Defined Konverteringar (C++/CLI)

I det här avsnittet beskrivs användardefinierade konverteringar (UDC) när en av typerna i konverteringen är en referens eller instans av en värdetyp eller referenstyp.

Implicita och explicita konverteringar

En användardefinierad konvertering kan antingen vara implicit eller explicit. En UDC bör vara implicit om konverteringen inte resulterar i förlust av information. Annars bör en explicit UDC definieras.

Konstruktorn för en inbyggd klass kan användas för att konvertera en referens- eller värdetyp till en intern klass.

Mer information om konverteringar finns i Boxning och Standardkonverteringar.

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

Resultat

in N::N
in N::N

Convert-From Operatörer

Konvertera från-operatorer skapar ett objekt i klassen där operatorn definieras från ett objekt i någon annan klass.

Standard C++ stöder inte konvertera från-operatorer. standard C++ använder konstruktorer för detta ändamål. Men när du använder CLR-typer ger Visual C++ syntaktisk support för att anropa konvertera från-operatorer.

Om du vill samverka väl med andra CLS-kompatibla språk kanske du vill omsluta varje användardefinierad unary-konstruktor för en viss klass med motsvarande convert-from-operator.

Konvertera från operatorer:

  • Ska definieras som statiska funktioner.

  • Kan antingen vara implicit (för konverteringar som inte förlorar precision, till exempel short-to-int) eller explicit, när precisionen kan gå förlorad.

  • Ska returnera ett objekt av den innehållande klassen.

  • Ska ha typen "från" som enskild parametertyp.

Följande exempel visar en implicit och explicit "convert-from", användardefinierad konverteringsoperator (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);
}

Resultat

in operator
in constructor
10
1

Konvertera till operatorer

Konvert-till-operatorer konverterar ett objekt i klassen där operatorn har definierats till ett annat objekt. Följande exempel visar en implicit, konvertera till, användardefinierad konverteringsoperator:

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

Resultat

10

En explicit användardefinierad konverteringsoperator är lämplig för konverteringar som potentiellt förlorar data på något sätt. Om du vill anropa en explicit konverteringstilloperator måste en kastning användas.

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

Resultat

10.3
10

Konvertera generiska klasser

Du kan konvertera en allmän klass till 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) );
}

Resultat

True

En konverterande konstruktor tar en typ och använder den för att skapa ett objekt. En konverterande konstruktor anropas endast med direkt initiering. casts anropar inte konverterande konstruktorer. Som standard är konvertering av konstruktorer explicita för CLR-typer.

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

Resultat

5
R

I det här kodexemplet gör en implicit statisk konverteringsfunktion samma sak som en explicit konverteringskonstruktor.

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

Resultat

13
12
500
2000

Se även

Klasser och strukturer