Ключевые слова default, delete. Примеры использования

Ключевые слова default, delete. Примеры использования


Содержание



1. Применение ключевого слова default. Общая форма

Ключевое слово default введено в C++ 11. Его использование указывает компилятору самостоятельно генерировать соответствующую функцию класса, если таковая не объявлена в классе. Компилятор автоматически генерирует ряд конструкторов класса и деструктор.

Общая форма использования ключевого слова default для конструкторов класса следующая:

class ClassName
{
    // ...

    ClassName(parameters) = default;

    // ...
};

где

  • ClassName – имя класса, в котором использовано ключевое слово default;
  • ClassName(parameters) – один из конструкторов класса, которые автоматически генерируются компилятором;
  • parameters – список параметров, который принимает специальная функция класса, которая генерируется автоматически. Список параметров может отсутствовать (конструктор по умолчанию).

Общая форма использования ключевого слова default для деструктора класса

class ClassName
{
    // ...

    ~ClassName(parameters) = default;

    // ...
};

 

2. К каким специальным функциям класса может быть применено ключевое слово default?

Ключевое слово default может применяться только к специальным функциям класса, которые при объявлении класса генерируются компилятором автоматически. К таким функциям относятся:

  • конструктор по умолчанию (default constructor);
  • конструктор копирования (copy constructor);
  • конструктор перемещения (move constructor);
  • оператор присваивания копированием (copy assignment operator);
  • оператор присваивания перемещением (move assignment operator);
  • деструктор (destructor).

 

3. Пример использования ключевого слова default для специальных функций класса, которые генерируются компилятором автоматически

Ниже продемонстрировано использование ключевого слова default для всех специальных функций класса, которые генерируются автоматически.

Объявляется класс Float, реализующий вещественное число.

В классе объявляются:

  • внутренняя скрытая (private) переменная x;
  • default-конструктор по умолчанию;
  • default-конструктор копирования;
  • default-конструктор перемещения;
  • default-оператор присваивания, выполняющий копирование;
  • default-оператор присваивания, выполняющий перемещение;
  • default-деструктор;
  • методы доступа Get(), Set().

 

// класс Float-демонстрация ключевого слова default
class Float
{
private:
  float x;

public:
  // Конструктор по умолчанию
  // ключевое слово default указывает компилятору самостоятельно формировать
  // соответствующий конструктор, если такой не объявлен в классе
  Float() = default;

  // конструктор с 1 параметром - не может быть применено default
  Float(float _x) :x(_x)
  { }

  // конструктор копирования - передача прав компилятору на формирование этого конструктора
  Float(const Float&) = default;

  // конструктор перемещения
  Float(Float&&) = default;

  // оператор присваивания копированием
  Float& operator=(const Float&) = default;

  // оператор присваивания перемещением
  Float& operator=(Float&&) = default;

  // деструктор
  ~Float() = default;

  // методы доступа
  float Get() { return x; }
  void Set(float _x) { x = _x; }
};

int main()
{
  // default - конструктор
  Float f1(7);
  Float f2 = f1;

  cout << "f2.x = " << f2.Get() << endl;
  Float f3;
  f3.Set(18);
  f3 = f2;
  cout << "f3.x = " << f3.Get() << endl;
}

Результат выполнения программы

f2.x = 7
f3.x = 7

 

4. Назначение ключевого слова delete. Общая форма объявления конструктора и метода класса с ключевым словом delete

Ключевое слово delete используется в случаях, когда нужно запретить автоматическое приведение типов в конструкторах и методах класса.

Общая форма объявления конструктора класса с ключевым словом delete

class ClassName
{
  // ...

  // конструкторы, которые запрещено использовать
  ClassName(parameters1) = delete;
  ClassName(parameters2) = delete;
  // ...
  ClassName(parametersN) = delete;

  // ...
};

где

  • parametes1, parameters2, …, parametersN – список параметров соответствующего конструктора класса.

Параметры могут отсутствовать. Если параметры конструктора отсутствуют, то запрещено использовать конструктор по умолчанию. В этом случае при объявлении

ClassName obj1;

компилятор будет выдавать ошибку

The default constructor of "ClassName" cannot be referenced – it is a deleted function

Ключевое слово delete может быть запрещено также и в методах. В этом случае, для метода с именем Func() общая форма объявления будет следующая

class ClassName
{
  // ...

  return_type Func(parameters) = delete;

  // ...
};

здесь

  • Func() – имя функции которую нужно запретить использовать в классе;
  • parameters – параметры функции;
  • return_type – тип, возвращаемый функцией.

 

5. Пример использования ключевого слова delete в классе

Задан класс Point реализующий точку на плоскости. В классе объявляются следующие элементы:

    • внутренние скрытые (private) переменные с именами x, y – координаты точки;
  • конструктор по умолчанию Point(), обозначенный ключевым словом default. Ключевое слово default указывает, что должен выполняться неявный конструктор по умолчанию, который автоматически генерируется компилятором;
  • конструктор Point(int) с одним параметром типа int;
  • конструктор с двумя параметрами Point(int, int);
  • методы доступа GetX(), GetY(), SetX(), SetY();
  • операторная функция operator+(), перегружающая бинарный оператор +;
  • операторная функция operator-(), перегружающая унарный оператор .

В классе запрещается использовать конструктор с одним параметром Point(double), принимающий параметр типа double. Этот конструктор обозначен ключевым словом delete. Однако, конструктор с параметром типа int разрешено использовать в классе.

Также запрещается использовать некоторые функции:

  • функцию SetX(double) с параметром типа double. Однако, Set(int) с параметром типа int разрешается использовать;
  • функцию SetXY(int, int) с двумя параметрами типа int.

Текст класса Point следующий:

#include <iostream>
using namespace std;

// Класс, реализующий точку на координатной плоскости
// в классе иследуются ключевые слова default и delete
class Point
{
private:
  int x = 0; // координаты точки
  int y = 0;

public:
  // default-конструктор, доверить реализацию компилятору
  Point() = default;

  // конструктор с одним параметром типа double - запрещено использовать
  Point(double value) = delete;

  // конструктор с одним параметром типа int - разрешено использовать
  Point(int value)
  {
    x = y = value;
  }

  // конструктор с 2 параметрами
  Point(int nx, int ny)
  {
    x = nx;
    y = ny;
  }

  // методы доступа к членам класса
  int GetX(void) { return x; }
  int GetY(void) { return y; }

  // функции SetX(), SetY() c параметром типа int
  void SetX(int nx) { x = nx; }
  void SetY(int ny) { y = ny; }

  // запретить вызов функции SetX(), SetY() с параметром типа double
  void SetX(double) = delete;

  // информация для компилятора, что запрещено использовать
  // метод SetXY() с двумя параметрами int
  void SetXY(int, int) = delete;

  // сам метод SetXY - ненужен, компилятор выдает ошибку
  /*
  void SetXY(int nx, int ny)
  {
    x = nx;
    y = ny;
  }
  */

  // перегруженный бинарный оператор '+'
  Point operator+(Point& pt)
  {
    // p - временный объект, который создается с помощью конструктора без параметров
    Point p;
    p.x = x + pt.x;
    p.y = y + pt.y;
    return p;
  }

  // перегруженный унарный оператор '-'
  Point operator-(void)
  {
    Point p;
    p.x = -x;
    p.y = -y;
    return p;
  }

  void Show(const char* objName)
  {
    cout << objName << ":" << endl;
    cout << "x=" << x << "; y=" << y << endl;
    cout << endl;
  }
};

void main()
{
  // 1. Объявление объекта с использованием конструктора с 1 параметром
  // 1.1. Ошибка компилятора
  //Point p1(5.5); //конструктор с 1 параметром типа double запрещен

  // 1.2. Разрешено использовать конструктор с 1 параметром типа int
  Point p1(5);
  p1.Show("p1");

  // 1.3. Запрещено использовать метод SetX() с параметром типа double
  // p1.SetX(5.5);
  p1.SetY(3.8); // а метод SetY() можно использовать
  p1.Show("p1");

  // 2. Объявление объекта без параметров - вызывается default-конструктор
  Point p3; // вызывается default-конструктор компилятора
  p3.Show("p3");

  // Объявление объекта с помощью конструктора с 2 параметрами
  Point p4(7, 8);
  p4.Show("p4");
}

Объясним некоторые фрагменты кода. Если в функции main() указать

Point p1(5.5);

то компилятор выдаст ошибку

(double)(5.5)
Function "Point::Point(double value)" declared at line (18) cannot be referenced - it is a deleted function

Это означает, что запрещено использовать конструктор с 1 параметром типа double. Однако, разрешено использовать конструктор с 1 параметром типа int, так как этот конструктор указан без ключевого слова delete.

В классе Point ключевое слово delete также применяется к функции

void SetX(double) = delete;

Это означает, что запрещено вызывать функцию SetX() с параметром типа double. Однако класс содержит другую функцию SetX() с параметром типа int

void SetX(int nx) { x = nx; }

которую разрешено вызывать. Таким образом в функции SetX() запрещается автоматическое приведение из типа double в тип int. По подобному примеру можно запретить автоматическое приведение типов для любых функций классов.

В демонстрационных целях показано, что в классе Point запрещено использовать функцию SetXY() с двумя параметрами

void SetXY(int, int) = delete;

Хотя, другой реализации данной функции в классе нет. Подобные запреты не реализованных функций в классе нормально воспринимаются компилятором.

 


Связанные темы