Что это значит в C #?
В C # семантика не связана с перегрузкой operator =
(чего вы не можете), но предоставляет оператор приведения любого типа к типу A или от типа A к любому типу.
Это означает следующий код (дополненный преобразованием A-типа):
class A {
public static implicit operator A(string s) {
return new A();
}
public static implicit operator A(double d) {
return new A();
}
public static implicit operator string(A a) {
return string.Empty;
}
public static implicit operator double(A a) {
return 0.0;
}
static void Main(string[] args) {
A a = "hello"; // line A
A b = 5.0; // line B
a = "World"; // line C
a = 3.14; // line D
double d = a ; // line E
string s = a ; // line F
}
}
работает для присваивания, либо в простых присваиваниях (например, строки C и D), либо в присваиваниях в объявлениях (например, строки A и B). Строки E и F показывают, как мы можем преобразовать пользовательский тип в другие типы.
Как это сделать в C ++?
В C ++ строки A и B являются объектными конструкциями, которые будут вызывать соответствующие конструкторы.
Строки C и D являются присвоением, которое вызывает соответствующий оператор присвоения.
Таким образом, код C ++ для предоставленного вами кода C # должен содержать как конструкторы, так и присваивания для строки и типа double, как показано ниже:
class A
{
public:
A(const std::string & s) { /*...*/ }
A(double d) { /*...*/ }
A & operator = (const std::string & s) { /*...*/ ; return *this ; }
A & operator = (double d) { /*...*/ ; return *this ; }
// etc.
} ;
Таким образом, вы можете иметь
void main()
{
A a0 = "Hello" ; // constructor
A a1("Hello") ; // constructor
A a2 = 5.0 ; // constructor
A a3(5.0) ; // constructor
a0 = "Hello World" ; // assignment
a0 = 3.14 ; // assignment
}
А как насчет операторов приведения в C ++?
Операторы приведения в C ++ работают подобно следующим операторам преобразования C #:
class A
{
static public operator string(A a) { /*... ; return a string */ }
static public operator double(A a) { /*... ; return a double */ }
// etc.
}
В C ++ операторы приведения записываются так:
class A
{
public:
operator std::string() { /*... ; return a string */ }
operator double() { /*... ; return a double */ }
// etc.
} ;
void main()
{
A a ;
std::string s ;
double d ;
// etc.
s = a ; // cast operator
d = a ; // cast operator
}
Почему это так сложно в C ++?
В C # оператор приведения / преобразования может быть записан из типа класса в любой тип или из любого типа в тип класса.
В C ++ для преобразования вы должны выбрать один или несколько способов, а именно: конструктор, оператор присваивания или оператор приведения, потому что в C ++ вы имеете детальный контроль над типами и операциями, и, следовательно, вы должны использовать этот мелкозернистый API.
Конструкции означают, что объект не существует, поэтому нет смысла конструировать его по какому-либо значению по умолчанию, а затем присвоить ему другое значение (это может стоить скорости). В C # тип ссылки / значения равен нулю / обнуляется перед присваиванием, поэтому это не проблема.
Назначение означает, что объект уже существует, поэтому можно использовать те же самые внутренние элементы, чтобы приспособить новое значение. В C # исходный эталонный объект отбрасывается, а другой создается (если создание стоит, что вы заплатите эту цену)
Что касается приведения, он используется в текущем случае для преобразования существующего класса в другой, для которого у вас нет контроля: вы не имеете права расширять std :: string, чтобы разместить конструктор для вашего класса, и нет способа добавить конструктор во встроенный тип, такой как double.