§ 2. Классы

2.3. Целочисленный тип данных

Рассмотрим примеры использования классов.

Пример 2.6. Реализовать класс для описания геометрической фигуры — Figure и его наследников — круг (Circle) и треугольник (Triangle). У базового класса нужно определить общий метод square(), который возвращает площадь геометрической фигуры, а у наследников  реализовать этот метод. Продемонстрировать работу методов.

Этапы выполнения задания

1. Описать базовый класс Figure.

    1. Базовый класс Figure является абстрактным классом, который будет содержать виртуальный метод square(). Виртуальный метод — это метод, который будет переопределен в классах-наследниках. Конкретная реализация метода при вызове будет определяться во время исполнения кода. В данном примере используется чистая виртуальная функция, которая вообще не имеет определения. Для того чтобы описать такую функцию, нужно просто присвоить ей значение 0. Определять ее будем в классах наследниках.
    2. Абстрактный класс должен содержать виртуальный деструктор, который позволит корректно удаляться объектам, созданным при наследовании.

2. Описать класс наследник Circle.

    1. При описании класса Circle нужно указать, что он является наследником класса Figure. Для этого после имени класса через символ «:» указать public Figure.
    2. Круг определяется своим радиусом, поэтому в классе определено поле radius.
    3. Описать конструктор, зависящий от радиуса.
    4. Описать метод вычисления площади. Площадь круга зависит от числа p, которое задано как константа вне класса.

3. Описать класс наследник Triangle.

    1. При описании класса Triangle нужно указать, что он является наследником класса Figure. Для этого после имени класса через символ «:» указать public Figure.
    2. Треугольник определяется длинами сторон, поэтому в классе определены поля a, b, c.
    3. Описать конструктор, зависящий от длин сторон.
    4. Описать метод вычисления площади. Площадь треугольника вычисляется по формуле Герона.

Пример 2.7. Задана дата рождения человека и текущая дата. Определить количество полных лет, прошедших со дня рождения. Для решения задачи использовать класс Data. Разделить объявление и определение класса, создав файлы Date.h и Date.cpp.

Этапы выполнения задания

1. Класс Date был описан в примере 22.5 учебного пособия 10 класса (http://profil.adu.by/mod/book/view.php?id=3574&chapterid=10521#pr5). В класс необходимо добавить функции-геттеры для получения дня, месяца и года.

2. Добавить файлы.

    1. Создать новый файл можно с помощью команды File → New  Empty file.
    2. Сохранить заголовочный файл под именем Date.h (h от англ. header — заголовок).
    3. Добавить еще один файл и сохранить его под именем Date.cpp.
    4. После добавления файлов изменится структура проекта:

    5. Путем перетаскивания окон файлы можно разместить так, чтобы они все были видны.

3. Заголовочный файл содержит объявление класса (реализацию) и описание библиотек (если они необходимы).

4. Файл Date.cpp содержит определение методов класса. Чтобы связать определение класса и его реализацию, необходимо в файле реализации подключить заголовочный файл с объявлением класса: #include "Date.h". Обратите внимание, что при подключении файла его имя берется в кавычки, а не в угловые скобки.

5. В файле main.cpp также необходимо подключить заголовочный файл.

 

Пример 2.6. Программа.

#include <iostream>

#include <cmath>

 

using namespace std;

 

double const pi = acos(-1);

 

/// базовый класс для фигур

class Figure

{

  public:

    virtual ~Figure() {}

    /// метод для вычисления площади

    virtual double square() const = 0;

};

 

/// класс для круга

class Circle : public Figure

{

  private:

    double radius;

  public:

    /// конструктор от радиуса

  Circle(double r) : radius(r) {}

    /// реализация метода square

  double square() const {

    return radius * radius * pi;

  }

};

 

/// класс для треугольника

class Triangle : public Figure

{

  private:

    double a, b, c;

  public:

    /// конструктор от длин сторон

    Triangle(double l1, double l2, double l3) :

        a(l1), b(l2), c(l3)  {}

    /// реализация метода square

    double square() const {

      double p = (+ b + c) / 2;

      double s = p * (- a) * 

            (- b) * (- c);

      return sqrt(s);

    }

 

    }

};

 

int main()

{

  double r;

  cout << "radius = ";

  cin >> r;

  Circle circle(r);

  cout << "S = " << circle.square() 

       << endl;

  double x, y, z;

  cout << "storony" << endl;

  cin >> x >> y >> z;

  Triangle ABC(x, y, z);

  cout << "S = " << ABC.square() << 

       endl;

    return 0;

}

Тестирование:

Абстрактный класс, который содержит только виртуальные методы, называется интерфейсом. Тогда абстрагирование — это необходимость сконцентрироваться на интерфейсе, не обращая внимания на реализацию.

Интерфейсы позволяют наладить множественное наследование объектов и решить проблему ромбовидного наследования (ситуация, когда два класса B и C наследуют от A, а класс D наследует от обоих классов B и C.

Имя интерфейса строится по тем же правилам, что и другие идентификаторы языка программирования. Однако для интерфейсов могут применяться дополнительные правила, которые помогают отличать имя интерфейса от имен других элементов программы. Например, в технологии COM и во всех поддерживающих её языках действует соглашение, следуя которому, имя интерфейса строится по шаблону «I<Имя>», то есть состоит из написанного с заглавной буквы осмысленного имени, которому предшествует заглавная латинская буква I, например IFigure.

Пример 2.7. Содержимое файла main.cpp.

#include <iostream>

#include <string>

#include <windows.h>

#include "Date.h"

 

using namespace std;

 

int main()

{

  SetConsoleCP(1251);

  SetConsoleOutputCP(1251);

  string s1, s2;

  cout << "Дата рождения - ";

  cin >> s1;

  cout << "Текущая дата - ";

  cin >> s2;

  Date d1(s1);

  Date d2(s2);

  int v = d2.get_Date_g() - d1.get_Date_g();

  if (d2.get_Date_m() < d1.get_Date_m())

    v --;

  else

    if (d2.get_Date_m() == d1.get_Date_m() &&

      d2.get_Date_d() < d1.get_Date_d())

        v--;

  cout << "возраст = " << v << endl;

  return 0

}

Содержимое файла Date.h.

#include <iostream>

#include <string>

#include "Date.h"

 

using namespace std;

 

Date::Date(int t_d, int t_m, int t_g)

{

    d = t_d;

    m = t_m;

    g = t_g;

}

 

Date::Date(string s)

{

   d = stoi(s.substr(0,2));

   m = stoi(s.substr(3,2));

   g = stoi(s.substr(6,4));

}

 

void Date::print()

{

cout << d << "." << m << "." << g;

}

 

string Date::get_Date_dm()

{

  string t1 = to_string(d);

  string t2 = to_string(m);

  return t1 + "." + t2;

}

 

int Date::get_Date_d()

{

    return d;

}

 

int Date::get_Date_m()

{

    return m;

}

 

int Date::get_Date_g()

{

    return g;

}