C++. Структури. Використання методів в структурах. Конструктори в структурах

Структури. Використання методів в структурах. Конструктори в структурах


Зміст


Пошук на інших ресурсах:




1. Особливості використання методів у структурах

У структурах можуть використовуватись методи. Використання методів у структурах нічим не відрізняється від використання методів у класах. Так само як і класи, в структурах можуть бути реалізовані конструктори.

Якщо в структурі оголошений метод без модифікатора доступу (private, protected, public), то цей метод за замовчуванням вважається загальнодоступним (public).

 

2. Як визначається розмір структури, яка містить методи? Приклад

Якщо в структурі оголошено методи, то вони не впливають на розмір структурної змінної, який визначається оператором sizeof. Розмір структурної змінної визначається тільки на основі внутрішніх даних, описаних в структурі.

Приклад. У прикладі оголошується структура Book без методів. У функції main() виводиться розмір структури, визначений оператором sizeof.

#include <iostream>
using namespace std;

// Структура Book, описує книгу
struct Book
{
  char title[100]; // назва книги
  char author[100]; // прізвище автора
  int year; // рік видання
  double price; // вартість
};

void main()
{
  // Визначити розмір структури Book
  Book b;
  int size = sizeof(b); // size = 216
  cout << "size = " << size << endl;
}

Якщо спробувати додати метод до структури, наприклад, так

struct Book
{
  char title[100]; // назва книги
  char author[100]; // прізвище автора
  int year; // рік видання
  double price; // вартість

  void Print()
  {
    cout << "title = " << title << endl;
    cout << "author = " << author << endl;
    cout << "year = " << year << endl;
    cout << "price = " << price << endl;
  }
};

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

size = 216

 

3. Приклад використання методів у структурах. Структура SquareEquition – розв’язок квадратного рівняння

Реалізовано структуру SquareEquition, що містить усі необхідні засоби для розв’язку квадратного рівняння.

Структура SquareEquition:

  • зберігає значення внутрішніх змінних a, b, c;
  • містить методи доступу до a, b, c;
  • виводить інформацію про розв’язок квадратного рівняння у зручній формі.

У структурі реалізовано:

  • приховані (private) внутрішні поля a, b, c, що є коефіцієнтами рівняння;
  • конструктор з трьома параметрами, які відповідають коефіцієнтам рівняння;
  • загальнодоступний (public) метод Solve(), який знаходить розв’язок квадратного рівняння;
  • загальнодоступний метод PrintSolve(), який виводить розв’язок квадратного рівняння на екран;
  • методи GetABC() та SetABC() для доступу до внутрішніх полів a, b, c.

 

#include <iostream>
using namespace std;

// Структура, що реалізує квадратне рівняння
struct SquareEquition
{
private:
  // внутрішні поля структури
  double a, b, c;

public:
  // Конструктор
  SquareEquition(double a, double b, double c)
  {
    this->a = a;
    this->b = b;
    this->c = c;
  }

  // Методи доступу
  void GetABC(double& a, double& b, double& c)
  {
    a = this->a;
    b = this->b;
    c = this->c;
  }

  void SetABC(double a, double b, double c)
  {
    this->a = a;
    this->b = b;
    this->c = c;
  }

  // Метод Solve().
  // - повертає true, якщо рівняння має розв'язок,
  // - повертає false, якщо рівняння не має розв'язку
  bool Solve(double& x1, double& x2)
  {
    // Перевірка, чи взагалі рівняння квадратне
    if (a == 0) return false;

    // обчислити дискримінант
    double d = b * b - 4 * a*c;

    // перевірка, чи рівняння має корені
    if (d < 0)
    {
      x1 = x2 = 0;
      return false;
    }

    // обчислення коренів
    x1 = (-b - sqrt(d)) / (2 * a);
    x2 = (-b + sqrt(d)) / (2 * a);

    return true;
  }

  // Метод, що виводить розв'язок квадратного рівняння,
  // даний метод звертається до методу Solve() для обчислення коренів рівняння.
  void PrintSolve()
  {
    double x1, x2;

    cout << "The equation: ";
    if (a != 0)
      cout << a << "*a";

    if (b != 0)
    {
      if (b > 0)
        cout << "+";
      cout << b << "*b";
    }

    if (c != 0)
    {
      if (c > 0)
        cout << "+";
      cout << c << "*c";
    }

    cout << " = 0" << endl;

    if (Solve(x1, x2)) // чи є розв'язок?
    {
      cout << "has the following roots: " << endl;
      cout << "x1 = " << x1 << endl;
      cout << "x2 = " << x2 << endl;
    }
    else
    {
      cout << "has no roots. ";
    }
  }
};

void main()
{
  // Структура SquareEquition
  SquareEquition e(-3, 1, 5.5); // виклик конструктора
  e.PrintSolve(); // виклик методу PrintSolve() структури
}

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

The equation: -3*a+1*b+5.5*c = 0
has the following roots:
x1 = 1.53089
x2 = -1.19756

 

4. Конструктори та деструктори в структурах. Особливості використання

Структури як і класи можуть містити конструктори. Для структур встановлено наступні правила застосування конструкторів:

  • структура може мати будь-яку кількість конструкторів, які відрізняються типами параметрів і/або кількістю параметрів;
  • структура може містити конструктори, які оголошені в розділах доступу: private, public, protected;
  • якщо в структурі немає жодного конструктора, то змінна (екземпляр) типу структури створюється звичайним способом без вказання параметрів;
  • якщо в структурі оголошено загальнодоступний конструктор, то екземпляр структури повинен обов’язково створюватись з параметрами, що відповідають цьому конструктору

У структурі також можуть використовуватись деструктори. Як правило, у деструкторах здійснюються операції звільнення використовуваних ресурсів, пам’яті, закриття використаних файлів тощо.

 

5. Приклад використання конструкторів та деструктора в структурі. Структури Point, ArrayPoint

У прикладі демонструється використання конструкторів та деструктора в структурах.

Оголошується дві структури:

  • структура Point, яка реалізує точку на координатній площині;
  • структура ArrayPoint – реалізує масив точок типу Point.

Структура типу Point містить наступні складові:

  • загальнодоступні (public) внутрішні змінні x, y;
  • конструктор без параметрів Point(), який ініціалізує внутрішні змінні нульовими значеннями;
  • конструктор з 2 параметрами Point(double, double) – ініціалізує внутрішні поля.

Структура типу ArrayPoint оголошує наступні елементи:

  • приховане (private) поле A – масив елементів типу Point;
  • приховане поле count – кількість елементів у масиві A;
  • конструктор ArrayPoint() без параметрів;
  • конструктор ArrayPoint(Point*, int) з параметром іншого масиву. Ініціалізує масив A елементами іншого масиву Point[];
  • конструктор копіювання ArrayPoint(const ArrayPoint&). Оскільки, в структурі ArrayPoint використовуються покажчики, то цей конструктор необхідний для коректної ініціалізації екземплярів структур типу ArrayPoint а також коректного повернення з функції екземпляру типу ArrayPoint;
  • методи доступу до елементів масиву GetP(int) та SetP(Point, int);
  • деструктор ~ArrayPoint(). У деструкторі звільняється пам’ять, виділена для масиву типу Point*;
  • метод Copy(const ArrayPoint&) копіювання одного масиву типу ArrayPoint в інший масив;
  • метод Print() – виводить елементи масиву ArrayPoint на екран.

У функції main() демонструється використання методів структури ArrayPoint.

Програма на мові C++ для шаблону Console Application.

#include <iostream>
using namespace std;

// Структура, що описує точку на координатній площині
struct Point
{
public:
  double x, y;

  // Конструктори
  Point()
  {
    x = y = 0;
  }

  Point(double _x, double _y) : x(_x), y(_y)
  { }
};

// Динамічний масив точок Point
struct ArrayPoint
{
private:
  Point* A; // покажчик на масив
  int count; // к-сть елементів у масиві

public:
  // Перевантажений конструктор Array()
  // Конструктор без параметрів
  ArrayPoint()
  {
    count = 0;
    A = nullptr;
  }

  // Конструктор з параметром іншого масиву
  ArrayPoint(Point* _A, int _count)
  {
    // Ініціалізувати масив A іншим масивом
    count = _count;
    A = new Point[count]; // виділити пам'ять

    for (int i = 0; i < count; i++)
    {
      A[i].x = _A[i].x;
      A[i].y = _A[i].y;
    }
  }

  // Конструктор копіювання.
  // Необхідний, тому що пам'ять в структурі виділяється динамічно
  ArrayPoint(const ArrayPoint& _A)
  {
    count = _A.count;

    // виділити пам'ять для масиву A
    A = new Point[count];

    // поелементне копіювання
    for (int i = 0; i < count; i++)
    {
      A[i].x = _A.A[i].x;
      A[i].y = _A.A[i].y;
    }
  }

  // Методи доступу до елементів масиву
  Point GetP(int index)
  {
    // Перевірка, чи індекс в допустимих межах
    if ((index >= 0) && (index < count))
    {
      return A[index];
    }

    // якщо індекс за межами, то повернути точку (0, 0)
    return Point();
  }

  void SetP(Point pt, int index)
  {
    // Перевірка, чи індекс в допустимих межах
    if ((index >= 0) && (index < count))
    {
      A[index].x = pt.x;
      A[index].y = pt.y;
    }
  }

  // Деструктор
  ~ArrayPoint()
  {
    // звільнити пам'ять, виділену для масиву A
    if (count > 0)
      delete[] A;
  }

  // Метод копіювання одного масиву Array в інший
  void Copy(const ArrayPoint& _A)
  {
    // Звільнити попередньо виділену пам'ять
    if (count > 0)
      delete[] A;

    // Виділити заново пам'ять
    count = _A.count;
    A = new Point[count];

    // поелементне присвоєння
    for (int i = 0; i < count; i++)
    {
      A[i].x = _A.A[i].x;
      A[i].y = _A.A[i].y;
    }
  }

  // Метод, що виводить масив A у зручній формі
  void Print()
  {
    cout << "A: " << endl;
    for (int i = 0; i < count; i++)
    {
      cout << "(" << A[i].x << ", " << A[i].y << ")";

      if (i != count - 1)
        cout << ", ";
    }
    cout << endl;
  }
};

void main()
{
  // Використання конструкторів та деструктора в структурі

  // Оголосити два масиви точок та інші внутрішні структури даних
  Point P1[3] = {
    Point(1.5, 2.8),
    Point(-1.3, 0.8),
    Point(-2.2, 5.5)
  };

  Point P2[2] = {
    Point(0.5,3.8),
    Point(2.9,1.6)
  };

  // Створити екземпляри масивів ArrayPoint
  ArrayPoint AP1(P1, 3);
  ArrayPoint AP2(P2, 2);

  // Вивести масиви AP1, AP2 для контролю
  cout << "AP1.";
  AP1.Print();

  cout << "---------------" << endl;
  cout << "AP2.";
  AP2.Print();

  // Перевірити конструктор копіювання, оголосити третій масив ArrayPoint
  ArrayPoint AP3 = AP1;
  cout << "----------------" << endl;
  cout << "AP3.";
  AP3.Print();

  // Перевірити метод Copy(), копіювання AP2=>AP3
  AP3.Copy(AP2);
  cout << "----------------" << endl;
  cout << "AP3.Copy(AP2) => AP3=AP2" << endl;
  cout << "AP2.";
  AP2.Print();
  cout << "AP3.";
  AP3.Print();

  // Перевірити метод GetP()
  Point pt1 = AP1.GetP(1);
  cout << "--------------" << endl;
  cout << "AP1[1] = (" << pt1.x << ", " << pt1.y << ")" << endl;
}

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

AP1.A:
(1.5, 2.8), (-1.3, 0.8), (-2.2, 5.5)
---------------
AP2.A:
(0.5, 3.8), (2.9, 1.6)
----------------
AP3.A:
(1.5, 2.8), (-1.3, 0.8), (-2.2, 5.5)
----------------
AP3.Copy(AP2) => AP3=AP2
AP2.A:
(0.5, 3.8), (2.9, 1.6)
AP3.A:
(0.5, 3.8), (2.9, 1.6)
--------------
AP1[1] = (-1.3, 0.8)

 


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