Генерация методов¶
В Ü ряд методов структур и классов может быть сгенерирован самим компилятором, нету нужны расписывать тела этих методов вручную.
К методам, которые компилятор может сгенерировать, относятся:
Конструкторы по умолчанию
Конструкторы копирования
Копирующие операторы присваивания
Деструкторы
Операторы сравнения на равенство (
==
)
Для того, чтобы какой-то метод мог быть сгенерирован, должен быть соблюдён ряд условий:
Для генерации конструктора по умолчанию необходимо, чтобы в классе или структуре все поля могли быть инициализированы по умолчанию и чтобы в классе или структуре не было ссылочных полей.
Для генерации конструктора копирования необходимо, чтобы в классе или структуре все поля были конструируемы копированием.
Для генерации копирующего оператора присваивания необходимо, чтобы в классе или структуре все поля могли быть копируемы присваиванием и чтобы не было неизменяемых или ссылочных полей.
Деструктор может быть сгенерирован всегда.
Для генерации оператора сравнения на равенство необходимо, чтобы в классе или структуре все поля можно было сравнивать на равенство и чтобы не было ссылочных полей.
Но возможность генерации метода не означает, что он будет сгенерирован. Явное объявление метода всегда отменяет его генерацию. Кроме того, есть ещё ряд условий:
Конструктор по умолчанию будет сгенерирован, только если нету явно объявленного конструктора по умолчанию и если нету явно объявленных других конструкторов, исключая конструктор копирования.
Конструктор копирования и оператор присваивания будут сгенерированы только для структур. Для классов они не могут быть сгенерированы явно.
Оператор сравнения на равенство также по умолчанию генерируется только для структур. Также он не будет сгенерирован, если в структуре есть другие операторы
==
.
А что же делать, если надо управлять генерацией методов явно? Для этого есть специальные конструкции - = delete
и = default
.
Данные конструкции указываются вместо тела соответствующего метода при объявлении.
= delete
сообщает компилятору, что данный метод не надо генерировать, даже если можно.
= default
сообщает компилятору, что данный метод надо генерировать. Если данный метод сгенерировать не получится, будет порождена ошибка.
Примеры:
class A
{
public:
fn constructor(i32 x) (x_= x) {}
fn constructor()= default; // Без этого конструктор не был бы сгенерирован, т. к. есть явный конструктор кроме конструктора копирования.
fn constructor(A& other)= default; // Без этого конструктор не был бы сгенерирован, т. к это класс.
op=(mut this, A& other)= default; // Без этого оператор присваивания не был бы сгенерирован, т. к это класс.
op==(A& l, A& r) : bool = default; // Без этого оператор сравнения на равенство не был бы сгенерирован, т. к это класс.
private:
i32 x_= 0;
}
struct B
{
fn constructor(B& other)= delete; // Без этого конструктор был бы сгенерирован, т. к это структура.
op=(mut this, B& other)= delete; // Без этого оператор присваивания был бы сгенерирован, т. к это структура.
op==(B& l, B& r) : bool = delete;// Без этого оператор сравнения на равенство был бы сгенерирован, т. к это структура.
i32 x;
}