При определении классов некоторые операции над их объектами будут определены по умолчанию.
• Конструктор по умолчанию.
• Копирующие операции (копирующее присваивание и копирующая инициализация).
• Деструктор.
Каждый из них (также по умолчанию) может рекурсивно применяться к каждому из своих базовых классов и членов. Создание производится снизу вверх, т.е. объект базового класса создается до создания членов производного класса. Члены производного класса и объекты базовых классов создаются в порядке их объявления и уничтожаются в обратном порядке. Таким образом, конструктор и деструктор всегда работают с точно определенными объектами базовых классов и членов производного класса. Рассмотрим пример.
struct D:B1, B2 {
M1 m1;
M2 m2;
};
Предполагая, что классы B1
, B2
, M1
и M2
определены, можем написать следующий код:
void f
{
D d; // инициализация по умолчанию
D d2 = d; // копирующая инициализация
d = D; // инициализация по умолчанию,
// за которой следует копирующее присваивание
} // объекты d и d2 уничтожаются здесь
Например, инициализация объекта d
по умолчанию выполняется путем вызова четырех конструкторов по умолчанию (в указанном порядке): B1::B1
, B2::B2
, M1::M1
и M2::M2
. Если один из этих конструкторов не определен или не может быть вызван, то создание объекта d
невозможно. Уничтожение объекта d
выполняется путем вызова четырех деструкторов (в указанном порядке): M2::~M2
, M1::~M1
, B2::~B2
и B1::~B1
. Если один из этих деструкторов не определен или не может быть вызван, то уничтожение объекта d
невозможно. Каждый из этих конструкторов и деструкторов может быть либо определен пользователем, либо сгенерирован автоматически.
Если класс имеет конструктор, определенный пользователем, то неявный (сгенерированный компилятором) конструктор по умолчанию остается неопределенным (не генерируется).
struct PPN {
unsigned int PFN: 22;
int: 3; // не используется
unsigned int CCA;
bool nonreacheable;
bool dirty;
bool valid;
bool global;
};
Упаковка битовых полей в виде слова слева направо приводит к следующему формату (см. раздел 25.5.5).
Битовое поле не обязано иметь имя, но если его нет, то к нему невозможно обратиться. Как это ни удивительно, но упаковка многих небольших значений в отдельное слово не всегда экономит память. На самом деле использование одного из таких значений приводит к излишнему расходу памяти по сравнению с использованием типа char
или int
даже для представления одного бита. Причина заключается в том, что для извлечения бита из слова и для записи бита в слово без изменения других битов необходимо выполнить несколько инструкций (которые также хранятся где-то в памяти). Не пытайтесь создавать битовые поля для экономии памяти, если у вас нет большого количества объектов с очень маленькими полями данных.
union U {
int x;
double d;
}
U a;
a.x = 7;
int x1 = a.x; // OK
a.d = 7.7;
int x2 = a.x; // Ой!
Правила согласованного чтения и записи членов объединения компилятором не проверяются. Мы вас предупредили.
template
class vector {
public:
// ...
int size const;
private:
int sz;
T* p;
};
template
int vector
{
return sz;
}
В списке шаблонных аргументов ключевое слово class
означает тип; его эквивалентной альтернативой является ключевое слово typename
. Функция-член шаблонного класса по умолчанию является шаблонной функцией с тем же списком шаблонных аргументов, что и у класса.
Целочисленные шаблонные аргументы должны быть константными выражениями.
template
class Fixed_array {
public:
T a[sz];
// ...
int size const { return sz; };
};
Fixed_array
int var = 226;
Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT