Создание объекта через указатель



Изучить теорию.

2. Тексты программ ввести в Dev C ++ и проверить правильность работы.

Весь реальный мир состоит из объектов. Города состоят из районов, в каждом районе есть свои названия улиц, на каждой улице находятся жилые дома, которые также состоят из объектов.

Практически любой материальный предмет можно представить в виде совокупности объектов, из которых он состоит. Допустим, что нам нужно написать программу для учета успеваемости студентов. Можно представить группу студентов, как класс языка C++. Назовем его Students.

· Основные понятия

· Модификаторы доступа public и private

· Программа учета успеваемости студентов

· Отделение данных от логики

· Создание объекта через указатель

· Конструктор и деструктор класса

class Students {

// Имя студента

string name;

// Фамилия

string last_name;

// Пять промежуточных оценок студента

int scores[5];

// Итоговая оценка за семестр

float average_ball;

};

Основные понятия

Классы в программировании состоят из свойств и методов. Свойства – это любые данные, которыми можно характеризовать объект класса. В нашем случае, объектом класса является студент, а его свойствами – имя, фамилия, оценки и средний балл.

У каждого студента есть имя – name и фамилия last_name . Также, у него есть промежуточные оценки за весь семестр. Эти оценки мы будем записывать в целочисленный массив из пяти элементов. После того, как все пять оценок будут проставлены, определим средний балл успеваемости студента за весь семестр – свойство average_ball.

Методы – это функции, которые могут выполнять какие-либо действия над данными (свойствами) класса. Добавим в наш класс функцию calculate_average_ball(), которая будет определять средний балл успеваемости ученика.

· Методы класса – это его функции.

· Свойства класса – его переменные.

class Students {

public:

   // Функция, считающая средний балл

   void calculate_average_ball()

   {

       int sum = 0; // Сумма всех оценок

       for (int i = 0; i < 5; ++i) {

           sum += scores[i];

       }

       // считаем среднее арифметическое

       average_ball = sum / 5.0;

   }

 

   // Имя студента

   string name;

   // Фамилия

   string last_name;

   // Пять промежуточных оценок студента

   int scores[5];

 

private:

   // Итоговая оценка за семестр

   float average_ball;

};

Функция calculate_average_ball() просто делит сумму всех промежуточных оценок на их количество.

Модификаторы доступа public и private

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

Закрытые данные класса размещаются после модификатора доступа private. Если отсутствует модификатор public, то все функции и переменные, по умолчанию являются закрытыми (как в первом примере).

Обычно, приватными делают все свойства класса, а публичными – его методы. Все действия с закрытыми свойствами класса реализуются через его методы. Рассмотрим следующий код.

class Students {

public:

   // Установка среднего балла

   void set_average_ball(float ball)

   {

       average_ball = ball;

   }

   // Получение среднего балла

   float get_average_ball()

   {

       return average_ball;

   }

   string name;

   string last_name;

   int scores[5];

 

private:

   float average_ball;

};

Мы не можем напрямую обращаться к закрытым данными класса. Работать с этими данными можно только посредством методов этого класса. В примере выше, мы используем функцию get_average_ball() для получения средней оценки студента, и set_average_ball() для выставления этой оценки.

Функция set_average_ball() принимает средний балл в качестве параметра и присваивает его значение закрытой переменной average_ball. Функция get_average_ball() просто возвращает значение этой переменной.

Программа учета успеваемости студентов

Создадим программу, которая будет заниматься учетом успеваемости студентов в группе. Создайте заголовочный файл students.h, в котором будет находиться класс Students.

/* students.h */

#include <string>

 

class Students {

public:

   // Установка имени студента

   void set_name(string student_name)

   {

       name = student_name;

   }

   // Получение имени студента

   string get_name()

   {

       return name;

   }

   // Установка фамилии студента

   void set_last_name(string student_last_name)

   {

       last_name = student_last_name;

   }

   // Получение фамилии студента

   string get_last_name()

   {

       return last_name;

   }

   // Установка промежуточных оценок

   void set_scores(int student_scores[])

   {

       for (int i = 0; i < 5; ++i) {

           scores[i] = student_scores[i];

       }

   }

   // Установка среднего балла

   void set_average_ball(float ball)

   {

       average_ball = ball;

   }

   // Получение среднего балла

   float get_average_ball()

   {

         return average_ball;

   }

 

private:

   // Промежуточные оценки

   int scores[5];

   // Средний балл

   float average_ball;

   // Имя

   string name;

   // Фамилия

   string last_name;

};

Мы добавили в наш класс новые методы, а также сделали приватными все его свойства. Функция set_name() сохраняет имя студента в переменной name, а get_name() возвращает значение этой переменной. Принцип работы функций set_last_name() и get_last_name() аналогичен.

Функция set_scores() принимает массив с промежуточными оценками и сохраняет их в приватную переменную int scores[5].

Теперь создайте файл main.cpp со следующим содержимым.

/* main.cpp */

#include <iostream>

#include "students.h"

 

int main()

{

// Создание объекта класса Student

Students student;

 

string name;

string last_name;

 

// Ввод имени с клавиатуры

cout << "Name: ";

getline(cin, name);

 

// Ввод фамилии

cout << "Last name: ";

getline(cin, last_name);

 

// Сохранение имени и фамилии в объект класса Students

student.set_name(name);

student.set_last_name(last_name);

 

// Оценки

int scores[5];

// Сумма всех оценок

int sum = 0;

 

// Ввод промежуточных оценок

for (int i = 0; i < 5; ++i) {

   cout << "Score " << i+1 << ": ";

   cin >> scores[i];

   // суммирование

   sum += scores[i];

}

 

// Сохраняем промежуточные оценки в объект класса Student

student.set_scores(scores);

// Считаем средний балл

float average_ball = sum / 5.0;

// Сохраняем средний балл в объект класса Students

student.set_average_ball(average_ball);

// Выводим данные по студенту

cout << "Average ball for " << student.get_name() << " "

    << student.get_last_name() << " is "

    << student.get_average_ball() << endl;

 

return 0;

}

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

Объект класса Students характеризует конкретного студента. Если мы захотим выставить оценки всем ученикам в группе, то будем создавать новый объект для каждого из них. Использование классов очень хорошо подходит для описания объектов реального мира.

После создания объекта student, мы вводим с клавиатуры фамилию, имя и промежуточные оценки для конкретного ученика. Пускай это будет Вася Пупкин, у которого есть пять оценок за семестр – две тройки, две четверки и одна пятерка.

Введенные данные мы передаем set-функциям, которые присваивают их закрытым переменным класса. После того, как были введены промежуточные оценки, мы высчитываем средний балл на основе этих оценок, а затем сохраняем это значение в закрытом свойстве average_ball, с помощью функции set_average_ball().

Скомпилируйте и запустите программу.

Отделение данных от логики

Вынесем реализацию всех методов класса в отдельный файл students.cpp.

/* students.cpp */

#include <string>

#include "students.h"

 

// Установка имени студента

void Students::set_name(string student_name)

{

Students::name = student_name;

}

 

// Получение имени студента

string Students::get_name()

{

return Students::name;

}

 

// Установка фамилии студента

void Students::set_last_name(string student_last_name)

{

Students::last_name = student_last_name;

}

 

// Получение фамилии студента

string Students::get_last_name()

{

return Students::last_name;

}

 

// Установка промежуточных оценок

void Students::set_scores(int scores[])

{

for (int i = 0; i < 5; ++i) {

   Students::scores[i] = scores[i];

}

}

 

// Установка среднего балла

void Students::set_average_ball(float ball)

{

Students::average_ball = ball;

}

 

// Получение среднего балла

float Students::get_average_ball()

{

return Students::average_ball;

}

А в заголовочном файле students.h оставим только прототипы этих методов.

/* students.h */

#pragma once /* Защита от двойного подключения заголовочного файла */

#include <string>

 

class Students {

public:

   // Установка имени студента

   void set_name(string);

   // Получение имени студента

   string get_name();

   // Установка фамилии студента

   void set_last_name(string);

   // Получение фамилии студента

   string get_last_name();

   // Установка промежуточных оценок

   void set_scores(int []);

   // Установка среднего балла

   void set_average_ball(float);

   // Получение среднего балла

   float get_average_ball();

 

private:

   // Промежуточные оценки

   int scores[5];

   // Средний балл

   float average_ball;

   // Имя

   string name;

   // Фамилия

   string last_name;

};

Такой подход называется абстракцией данных – одного из фундаментальных принципов объектно-ориентированного программирования. К примеру, если кто-то другой захочет использовать наш класс в своем коде, ему не обязательно знать, как именно высчитывается средний балл. Он просто будет использовать функцию calculate_average_ball() из второго примера, не вникая в алгоритм ее работы.

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

В начале обучения мы говорили о пространствах имен (namespaces). Каждый класс в C++ использует свое пространство имен. Это сделано для того, чтобы избежать конфликтов при именовании переменных и функций. В файле students.cpp мы используем оператор принадлежности :: перед именем каждой функции. Это делается для того, чтобы указать компилятору, что эти функции принадлежат классу Students.

Создание объекта через указатель

При создании объекта, лучше не копировать память для него, а выделять ее в в куче с помощью указателя. И освобождать ее после того, как мы закончили работу с объектом. Реализуем это в нашей программе, немного изменив содержимое файла main.cpp.

/* main.cpp */

#include <iostream>

#include "students.h"

 

int main()

{

// Выделение памяти для объекта Students

Students *student = new Students;

 

string name;

string last_name;

 

// Ввод имени с клавиатуры

cout << "Name: ";

getline(cin, name);

 

// Ввод фамилии

cout << "Last name: ";

getline(cin, last_name);

 

// Сохранение имени и фамилии в объект класса Students

student->set_name(name);

student->set_last_name(last_name);

 

// Оценки

int scores[5];

// Сумма всех оценок

int sum = 0;

 

// Ввод промежуточных оценок

for (int i = 0; i < 5; ++i) {

   cout << "Score " << i+1 << ": ";

   cin >> scores[i];

   // суммирование

   sum += scores[i];

}

// Сохраняем промежуточные оценки в объект класса Student

student->set_scores(scores);

 

// Считаем средний балл

float average_ball = sum / 5.0;

// Сохраняем средний балл в объект класса Students

student->set_average_ball(average_ball);

// Выводим данные по студенту

cout << "Average ball for " << student->get_name() << " "

    << student->get_last_name() << " is "

    << student->get_average_ball() << endl;

// Удаление объекта student из памяти

delete student;

return 0;

}

При создании статического объекта, для доступа к его методам и свойствам, используют операция прямого обращения – «.» (символ точки). Если же память для объекта выделяется посредством указателя, то для доступа к его методам и свойствам используется оператор косвенного обращения – «->».


Дата добавления: 2021-07-19; просмотров: 65; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!