Uživatelem definované převody (C++/CLI)
Tato část popisuje uživatelem definované převody (UDC), pokud jeden z typů v převodu je odkaz nebo instance typu hodnoty nebo referenčního typu.
Implicitní a explicitní převody
Převod definovaný uživatelem může být implicitní nebo explicitní. UDC by měl být implicitní, pokud převod nezpůsobí ztrátu informací. Jinak by se mělo definovat explicitní UDC.
Konstruktor nativní třídy lze použít k převodu odkazu nebo typu hodnoty na nativní třídu.
// 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);
}
Výstup
in N::N
in N::N
Operátory Convert-From
Převod operátorů vytvoří objekt třídy, ve které je operátor definován z objektu některé jiné třídy.
Standard C++ nepodporuje převod z operátorů; Standard C++ používá pro tento účel konstruktory. Při použití typů CLR ale Visual C++ poskytuje syntaktickou podporu volání operátorů převodu z operátorů.
Pokud chcete dobře spolupracovat s jinými jazyky odpovídajícími cls, můžete chtít zabalit každý uživatelem definovaný unární konstruktor pro danou třídu s odpovídajícím operátorem convert-from.
Převod operátorů:
Musí být definovány jako statické funkce.
Může být buď implicitní (pro převody, které nepřijdou o přesnost, jako je zkratka na int), nebo explicitní, pokud může dojít ke ztrátě přesnosti.
Vrátí objekt obsahující třídy.
Musí mít typ "from" jako jediný typ parametru.
Následující ukázka ukazuje implicitní a explicitní operátor převodu definovaný uživatelem (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);
}
Výstup
in operator
in constructor
10
1
Převod na operátory
Convert-to operators convert an object of the class in which the operator is defined to some other object. Následující ukázka ukazuje implicitní operátor převodu na převod definovaný uživatelem:
// 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);
}
Výstup
10
Explicitní uživatelem definovaný operátor převodu na převod je vhodný pro převody, které potenciálně ztratí data nějakým způsobem. Chcete-li vyvolat explicitní operátor convert-to, je nutné použít přetypování.
// 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);
}
Výstup
10.3
10
Převod obecných tříd
Obecnou třídu můžete převést na 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) );
}
Výstup
True
Převáděcí konstruktor přebírá typ a používá ho k vytvoření objektu. Konvertující konstruktor je volána pouze s přímým inicializací; casts will not invokeing converting constructors. Ve výchozím nastavení jsou převod konstruktory explicitní pro typy 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);
}
Výstup
5
R
V této ukázce kódu dělá implicitní statická konverzní funkce totéž jako explicitní konstruktor převodu.
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);
}
Výstup
13
12
500
2000