explicit operator int() const { return val; }
//
};
Подобно явным конструкторам (см. раздел 7.5.4), компилятор не будет (обычно) использовать явный оператор преобразования для неявных преобразований:
SmallInt si = 3; //
si + 3; //
//
static_cast
Если оператор преобразования является явным, такое преобразование вполне можно осуществить. Но за одним исключением такое приведение следует осуществить явно.
Исключение состоит в том, что компилятор применит явное преобразование в выражении, используемом как условие. Таким образом, явное преобразование будет использовано неявно для преобразования выражения, используемого как:
• условие оператора if, while или do;
• выражение условия в заголовке оператора for;
• операнд логического оператора NOT (!), OR (||) или AND (&&);
• выражение условия в условном операторе (?:).
boolВ прежних версиях библиотеки типы ввода-вывода определяли преобразование в тип void*. Это было сделано во избежание проблем, описанных выше. По новому стандарту библиотека ввода-вывода определяет вместо этого явное преобразование в тип bool.
Всякий раз, когда потоковый объект используется в условии, применяется оператор operator bool(), определенный для типов ввода-вывода. Например:
while (std::cin >> value)
Условие в операторе while выполняет оператор ввода, который читает в переменную value и возвращает объект cin. Для обработки условия объект cin неявно преобразуется функцией преобразования istream::operator bool(). Эта функция возвращает значение true, если флагом состояния потока cin является good (см. раздел 8.1.2), и false в противном случае.
bool обычно используется в условиях. В результате оператор operator bool обычно должен определяться как явный.
Упражнение 14.45. Напишите операторы преобразования для преобразования объекта класса Sales_data в значения типа string и double. Какие значения, по-вашему, должны возвращать эти операторы?
Упражнение 14.46. Объясните, является ли определение этих операторов преобразования класса Sales_data хорошей идеей и должны ли они быть явными.
Упражнение 14.47. Объясните различие между этими двумя операторами преобразования:
struct Integral {
operator const int();
operator int() const;
};
Упражнение 14.48. Должен ли класс из упражнения 7.40 раздела 7.5.1 использовать преобразование в тип bool. Если да, то объясните почему и укажите, должен ли оператор быть явным. В противном случае объясните, почему нет.
Упражнение 14.49. Независимо от того, хороша ли эта идея, определите преобразование в тип bool для класса из предыдущего упражнения.
Если у класса есть один или несколько операторов преобразования, важно гарантировать наличие только одного способа преобразования из типа класса в необходимый тип. Если будет больше одного способа осуществления преобразования, то будет весьма затруднительно написать однозначный код.
Есть два случая, когда возникает несколько путей осуществления преобразования. Первый — когда два класса обеспечивают взаимное преобразование. Например, взаимное преобразование осуществляется тогда, когда класс А определяет конструктор преобразования, получающий объект класса B, а класс в определяет оператор преобразования в тип А.
Второй случай возникновения нескольких путей преобразования — определение нескольких преобразований в и из типов, которые сами связаны преобразованиями. Самый очевидный пример — встроенные арифметические типы. Каждый класс обычно должен определять не больше одного преобразования в или из арифметического типа.
В следующем примере определены два способа получения объекта класса А из В: либо при помощи оператора преобразования класса В, либо при помощи конструктора класса А, получающего объект класса В:
//
struct B;
struct А {
А() = default;
A(const В&); //
//
};