Категории
Самые читаемые
RUSBOOK.SU » Компьютеры и Интернет » Программирование » Справочное руководство по C++ - Бьярн Страустрап

Справочное руководство по C++ - Бьярн Страустрап

Читать онлайн Справочное руководство по C++ - Бьярн Страустрап

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 20 21 22 23 24 25 26 27 28 ... 41
Перейти на страницу:

Конструктор копирования для класса X не должен иметь в качестве параметра объект типа X, например X::X(X) незаконное обращение.

Конструктор для массива элементов вызывается в порядке возрастания адресов элементов (§R.8.2.4).

Если у класса есть базовые классы с конструктором или члены, являющиеся объектами с конструктором, их конструкторы вызываются прежде, чем конструктор производного класса. В §R.12.6.2 объясняется как задаются параметры для таких конструкторов и как определяется порядок их вызова.

Объект класса с конструктором не может быть членом объединения.

Для конструктора не нужно указывать никакого типа возвращаемого значения, даже void. В операторе return в теле конструктора нельзя указывать возвращаемое значение. Не допустима операция взятия адреса конструктора.

Конструктор можно явно использовать для создания объектов его типа с помощью следующей записи:

имя-класса ( список-выражений opt )

Приведем пример:

complex zz = complex(1,2.3);

print(complex(7.8,1.2));

Объект, созданный таким образом является безымянным (если только конструктор не использовался для инициализации поименованной переменной как zz выше), а время его жизни ограничено выражением, в котором он был создан, см. §R.12.2.

В конструкторе можно вызывать функцию-член, см. §R.12.7.

R.12.2 Временные объекты

В некоторых ситуациях транслятору бывает необходимо или удобно создавать временные объекты. Использование временных объектов зависит от реализации. Если транслятору понадобился временный объект типа класса с конструктором, он должен обеспечить вызов конструктора для этого временного объекта. Аналогично, необходимо вызывать деструктор для объекта класса, в котором описан деструктор. Приведем пример:

class X {

 //…

public:

 //…

 X(int);

 X(X&);

 ~X();

};

X f(X);

void g()

{

 X a(1);

 X b = f(X(2));

 a = f(b);

}

Здесь нужен временный объект для построения X(2), прежде чем передать его функции f() с помощью X(X&). Альтернативное решение, - построить объект X(2) в памяти, используемой для хранения параметра при первом вызове f(). Помимо этого, временный объект может понадобиться для хранения результата f(X(2)) прежде, чем копировать его в объект b с помощью X(X&), и здесь возможно альтернативное решение: хранить результат f(X(2)) в памяти для объекта b. С другой стороны, существует много функций f(), для которых выполнение выражения a=f(a) требует временного объекта или для параметра a, или для результата f(a), чтобы избежать нежелательного использования памяти, которой приписывается имя a.

Транслятор обязан гарантировать уничтожение временных объектов. Точный момент уничтожения определяется реализацией. С временными объектами можно производить только две операции: выбрать значение объекта (неявно копируя его) для использования в другом выражении, или взять ссылку на него. Если значение временного объекта получено, он считается ненужным и может уничтожаться немедленно. Если на него получена ссылка, то уничтожать его нельзя, пока существует ссылка. Уничтожение должно произойти до выхода из области определенности, в которой был создан временный объект.

Другой вид временных объектов обсуждается в §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 Деструкторы

Деструктором называется функция-член класса cl с именем ~cl, она используется для уничтожения значений типа cl непосредственно перед уничтожением объекта, содержащего их. Деструктор не имеет формальных параметров и для него нельзя задать тип возвращаемого значения (даже void). Нельзя применять операцию взятия адреса для деструктора. Можно вызывать деструктор для объектов со спецификацией const или volatile, но сам деструктор нельзя описывать с этими спецификациями (§R.9.3.1). Деструктор не может быть и статическим.

Деструкторы не наследуются. Если базовый класс или член имеют деструктор, а сам производный класс - нет, то создается стандартный деструктор, который вызывает деструкторы базовых классов и членов производного класса. Такие созданные деструкторы имеют спецификацию public.

1 ... 20 21 22 23 24 25 26 27 28 ... 41
Перейти на страницу:
На этой странице вы можете бесплатно скачать Справочное руководство по C++ - Бьярн Страустрап торрент бесплатно.
Комментарии
Открыть боковую панель
Комментарии
Вася
Вася 24.11.2024 - 19:04
Прекрасное описание анального секса
Сергій
Сергій 25.01.2024 - 17:17
"Убийство миссис Спэнлоу" от Агаты Кристи – это великолепный детектив, который завораживает с первой страницы и держит в напряжении до последнего момента. Кристи, как всегда, мастерски строит