Delen via


User-Defined Conversies (C++/CLI)

In deze sectie worden door de gebruiker gedefinieerde conversies (UDC) besproken wanneer een van de typen in de conversie een verwijzing of exemplaar van een waardetype of verwijzingstype is.

Impliciete en expliciete conversies

Een door de gebruiker gedefinieerde conversie kan impliciet of expliciet zijn. Een UDC moet impliciet zijn als de conversie geen verlies van informatie tot gevolg heeft. Anders moet een expliciete UDC worden gedefinieerd.

De constructor van een systeemeigen klasse kan worden gebruikt om een verwijzing of waardetype te converteren naar een systeemeigen klasse.

Raadpleeg Boxing en Standaardconversies voor meer informatie over conversies.

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

Uitvoer

in N::N
in N::N

operators voor Convert-From

Converteer-van-operatoren maken een object van de klasse waarin de operator is gedefinieerd van een object uit een andere klasse.

Standard C++ biedt geen ondersteuning voor convert-from-operators; standaard C++ maakt gebruik van constructors voor dit doel. Bij het gebruik van CLR-typen biedt Visual C++ echter syntactische ondersteuning voor het aanroepen van convert-from-operators.

Als u goed wilt samenwerken met andere CLS-conforme talen, kunt u elke door de gebruiker gedefinieerde unary constructor verpakken voor een bepaalde klasse met een bijbehorende convert-from-operator.

Converteren van operators:

  • Moet worden gedefinieerd als statische functies.

  • Kan impliciet zijn (voor conversies die geen precisie verliezen, zoals short-to-int) of expliciet, wanneer er mogelijk sprake is van een verlies van precisie.

  • Retourneert een object van de bevatde klasse.

  • Moet het type 'van' hebben als het enige parametertype.

In het volgende voorbeeld ziet u een impliciete en expliciete UDC-operator (convert-from), door de gebruiker gedefinieerde conversieoperator.

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

Uitvoer

in operator
in constructor
10
1

Converteren naar operators

Convert-to-operators converteren een object van de klasse waarin de operator is gedefinieerd in een ander object. In het volgende voorbeeld ziet u een impliciete, naar-gebruiker-gedefinieerde conversieoperator:

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

Uitvoer

10

Een expliciet door de gebruiker gedefinieerde conversieoperator is geschikt voor conversies die mogelijk gegevens op een of andere manier verliezen. Als u een expliciete conversie-naar-operator wilt aanroepen, moet een cast worden gebruikt.

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

Uitvoer

10.3
10

Het converteren van algemene klassen

U kunt een algemene klasse converteren naar 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) );
}

Uitvoer

True

Een conversieconstructor neemt een type en gebruikt dit om een object aan te maken. Een conversieconstructor wordt alleen aangeroepen met directe initialisatie; casts roepen geen conversieconstructors aan. Het converteren van constructors is standaard expliciet voor CLR-typen.

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

Uitvoer

5
R

In dit codevoorbeeld doet een impliciete statische conversiefunctie hetzelfde als een expliciete conversieconstructor.

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

Uitvoer

13
12
500
2000

Zie ook

Klassen en Structs