Например, инициализация объекта d
B1::B1()
, B2::B2()
, M1::M1()
и M2::M2()
. Если один из этих конструкторов не определен или не может быть вызван, то создание объекта d
невозможно. Уничтожение объекта d
выполняется путем вызова четырех деструкторов (в указанном порядке): M2::~M2()
, M1::~M1()
, B2::~B2()
и B1::~B1()
. Если один из этих деструкторов не определен или не может быть вызван, то уничтожение объекта d
невозможно. Каждый из этих конструкторов и деструкторов может быть либо определен пользователем, либо сгенерирован автоматически.Если класс имеет конструктор, определенный пользователем, то неявный (сгенерированный компилятором) конструктор по умолчанию остается неопределенным (не генерируется).
A.12.5. Битовые поля
struct PPN {
unsigned int PFN: 22;
int: 3; // не используется
unsigned int CCA;
bool nonreacheable;
bool dirty;
bool valid;
bool global;
};
Упаковка битовых полей в виде слова слева направо приводит к следующему формату (см. раздел 25.5.5).
Битовое поле не обязано иметь имя, но если его нет, то к нему невозможно обратиться. Как это ни удивительно, но упаковка многих небольших значений в отдельное слово не всегда экономит память. На самом деле использование одного из таких значений приводит к излишнему расходу памяти по сравнению с использованием типа char
int
даже для представления одного бита. Причина заключается в том, что для извлечения бита из слова и для записи бита в слово без изменения других битов необходимо выполнить несколько инструкций (которые также хранятся где-то в памяти). Не пытайтесь создавать битовые поля для экономии памяти, если у вас нет большого количества объектов с очень маленькими полями данных.A.12.6. Объединения
union U {
int x;
double d;
}
U a;
a.x = 7;
int x1 = a.x; // OK
a.d = 7.7;
int x2 = a.x; // Ой!
Правила согласованного чтения и записи членов объединения компилятором не проверяются. Мы вас предупредили.
A.13. Шаблоны
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;
Fixed_array
A.13.1. Шаблонные аргументы
Аргументы шаблонного класса указываются каждый раз, когда используется его имя.
vector
vector v2; // ошибка: пропущен шаблонный аргумент
vector
vector<2> v4; // ошибка: ожидается тип шаблонного аргумента
Аргументы шаблонной функции обычно выводятся из ее аргументов.
template
T find(vector
{
return v[i];
}
vector
vector
// ...
int x1 = find(v1,2); // здесь тип T — это int
int x2 = find(v2,2); // здесь тип T — это double
Можно объявить шаблонную функцию, для которой невозможно вывести ее шаблонные аргументы. В этом случае мы должны конкретизировать шаблонные аргументы явно (точно так же, как для шаблонных классов). Рассмотрим пример.