Ключові слова 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; }
};

void 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. Однак, SetX(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() з параметром типу 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;

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

 


Зв’язані теми