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)

 


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