Генерация методов¶
В Ü ряд методов структур и классов может быть сгенерирован самим компилятором, нету нужны расписывать тела этих методов вручную.
К методам, которые компилятор может сгенерировать, относятся:
- Конструкторы по умолчанию
- Конструкторы копирования
- Копирующие операторы присваивания
- Деструкторы
- Операторы сравнения на равенство (
==
)
Для того, чтобы какой-то метод мог быть сгенерирован, должен быть соблюдён ряд условий:
- Для генерации конструктора по умолчанию необходимо, чтобы в классе или структуре все поля могли быть инициализированы по умолчанию и чтобы в классе или структуре не было ссылочных полей.
- Для генерации конструктора копирования необходимо, чтобы в классе или структуре все поля были конструируемы копированием.
- Для генерации копирующего оператора присваивания необходимо, чтобы в классе или структуре все поля могли быть копируемы присваиванием и чтобы не было неизменяемых или ссылочных полей.
- Деструктор может быть сгенерирован всегда.
- Для генерации оператора сравнения на равенство необходимо, чтобы в классе или структуре все поля можно было сравнивать на равенство и чтобы не было ссылочных полей.
Но возможность генерации метода не означает, что он будет сгенерирован. Явное объявление метода всегда отменяет его генерацию. Кроме того, есть ещё ряд условий:
- Конструктор по умолчанию будет сгенерирован, только если нету явно объявленного конструктора по умолчанию и если нету явно объявленных других конструкторов, исключая конструктор копирования.
- Конструктор копирования и оператор присваивания будут сгенерированы только для структур. Для классов они не могут быть сгенерированы явно.
- Оператор сравнения на равенство также по умолчанию генерируется только для структур. Также он не будет сгенерирован, если в структуре есть другие операторы
==
.
А что же делать, если надо управлять генерацией методов явно? Для этого есть специальные конструкции - = 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;
}