Другой вид временных объектов обсуждается в §R.8.4.3.
R.12.3 Преобразования
Преобразования объектов класса можно задать с помощью конструкторов или функций преобразования.
Такие преобразования, обычно называемые пользовательскими, используются неявно в совокупности со стандартными преобразованиями (§R.4). Например, функцию с формальным параметром типа X можно вызывать не только с параметром типа X, но и параметром типа T, если существует преобразование типа T в X. Пользовательские преобразования применяются в тех же ситуациях, что и стандартные: преобразование инициализаторов (§R.8.4), параметров функции (§R.5.2.2), возвращаемых функцией значений (§R.6.6.3, §R.8.2.5), выражений фактических параметров (§R.5), выражений, управляющих циклом и выбором операторов (§R.6.4, §R.6.5) и явные операции преобразования типа (§R.5.2.3, §R.5.4).
Пользовательские преобразования применяются только в случае их однозначности (§R.10.1.1, §R.12.3.2). Преобразования проходят проверку на соответствие правилам доступа (§R.11). Как всегда проверка доступа осуществляется после разрешения неоднозначности (§R.10.4).
Применение преобразований при вызове функции рассматривается на примерах, приведенных ниже, а также обсуждается в §R.13.2.
R.12.3.1 Преобразование с помощью конструктора
Конструктор, имеющий единственный параметр, задает преобразование типа своего фактического параметра в тип его класса, например:
class X {
//…
public:
X(int);
X(const char*, int = 0);
};
void f(X arg) {
X a = 1; // a = X(1);
X b = "Jessie"; // b = X("Jessie",0)
a = 2; // a = X(2)
f(3); // f(X(3))
}
Если в классе X нет конструктора, который допускает заданный тип, не делается попытки найти какой-либо конструктор другого класса или функцию преобразования для приведения заданного значения в значение типа,допустимого для конструктора класса X, например:
class X { /*… */ X(int); };
class Y { /*… */ Y(X); };
Y a = 1; // недопустимо: преобразование Y(X(1))
// не применяется
R.12.3.2 Функции преобразования
Функция-член класса X, имя которой имеет вид,
имя-функции-преобразования:
operator имя-типа-преобразования
имя-типа-преобразования:
список-спецификаций-типа opt операция-ptr opt
задает преобразование из типа X в тип, определяемый конструкцией имя-типа-преобразования. Такие функции-члены называются функциями преобразования. В конструкции список-спецификаций-типа нельзя описывать классы, перечисления и имена-typedef, а также нельзя задавать типы формальных параметров и тип возвращаемого значения.
Приведем пример:
class X {
//…
public:
operator int();
};
void f(X a)
{
int i = int(a);
i = (int)a;
i = a;
}
Здесь во всех трех операторах присваиваемое значение будет преобразовываться с помощью функции X::operator int(). Пользовательские преобразования не ограничиваются только использованием в присваивании и инициализации, например:
void g(X a, X b)
{
int i = (a) ? 1+a : 0;
int j = (a&&b) ? a+b : i;
if (a) {//…
}
}
Операции преобразования наследуются. Функции преобразования могут быть виртуальными.
К данному значению неявно применяется не более одного пользовательского преобразования (с помощью конструктора или функции преобразования), например:
class X {
//…
public:
operator int();
};
class Y {
//…
public:
operator X();
};
Y a;
int b = a; // недопустимо: преобразование
// a.operator X().operator int() не применяется
int c = X(a); // нормально: a.operator X().operator int()
Пользовательские преобразования осуществляются неявно только при условии их однозначности. Функция преобразования производного класса не закрывает функцию преобразования базового класса, если только они не преобразуют к одному и тому же типу, например:
class X {
public:
//…
operator int();
};
class Y: public X {
public:
//…
operator void*();
};
void f(Y& a)
{
if (a) {// ошибка: неоднозначность
}
}
R.12.4 Деструкторы