使用者定義轉換 (C++/CLI)
本節討論轉換中的其中一個型別是實值型別或參考型別的實例時,使用者定義轉換 (UDC)。
隱含和明確轉換
使用者定義的轉換可以是隱含或明確轉換。 如果轉換不會導致資訊遺失,UDC 應該是隱含的。 否則應該定義明確的 UDC。
原生類別的建構函式可用來將參考或實值型別轉換成原生類別。
// 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);
}
輸出
in N::N
in N::N
轉換來源運算子
Convert-from 運算子會建立 類別的物件,其中運算子是從某些其他類別的物件定義。
標準 C++ 不支援從運算子轉換;標準 C++ 會針對此目的使用建構函式。 不過,使用 CLR 類型時,Visual C++ 會提供語法支援來呼叫 convert-from 運算子。
若要與其他符合 CLS 規範的語言互通,您可能想要使用對應的 convert-from 運算子,包裝指定類別的每個使用者定義一元建構函式。
轉換自運算子:
應定義為靜態函式。
可以是隱含的(對於不會遺失精確度的轉換,例如 short-to-int)或明確,當可能會遺失有效位數時。
應該傳回包含類別的 物件。
應將 「from」 類型作為唯一的參數類型。
下列範例顯示隱含且明確的「轉換-from」使用者定義轉換 (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);
}
輸出
in operator
in constructor
10
1
轉換成運算子
Convert-to 運算子會轉換 類別的物件,其中運算子會定義為一些其他物件。 下列範例顯示隱含、轉換為使用者定義轉換運算子:
// 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);
}
輸出
10
明確的使用者定義轉換轉換運算子適用于可能以某種方式遺失資料的轉換。 若要叫用明確的 convert-to 運算子,必須使用轉換。
// 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);
}
輸出
10.3
10
轉換泛型類別
您可以將泛型類別轉換成 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) );
}
輸出
True
轉換建構函式會採用型別,並用它來建立物件。 僅使用直接初始化呼叫轉換建構函式;轉換不會叫用轉換建構函式。 根據預設,轉換建構函式是 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);
}
輸出
5
R
在此程式碼範例中,隱含靜態轉換函式會執行與明確轉換建構函式相同的動作。
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);
}
輸出
13
12
500
2000