Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка_new_ООП.doc
Скачиваний:
3
Добавлен:
09.11.2019
Размер:
133.63 Кб
Скачать

20

Лабораторная работа №1 создание классов

Цель работы: Получить практические навыки проектирования и реализации классов

    1. Теоретические сведения Классы

Объект — это совокупность отдельных информационных элементов и функций, которые им оперируют. Объект состоит из следующих трех частей:

  • имя объекта;

  • состояние (переменные состояния);

  • методы (операции).

Объект ООП — это совокупность переменных состояния и связанных с ними методов (операций). Эти методы определяют как объект взаимодействует с окружающим миром.

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

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

Класс (class) — это группа данных и методов (функций) для работы с этими данными.

Объект (object) — это конкретная реализация, экземпляр класса. В программировании отношения объекта и класса можно сравнить с описанием переменной, где сама переменная (объект) является экземпляром какого — либо типа данных (класса).

Обычно, если объекты соответствуют конкретным сущностям реального мира, то классы являются некими абстракциями, выступающими в роли понятий. Для формирования какого—либо реального объекта необходимо иметь шаблон, на основании которого и строится создаваемый объект. При рассмотрении основ ООП очень часто смешивают понятия объекта и класса. Дело в том, что класс — это некоторое абстрактное понятие. Для проведения аналогий или приведения примеров оно не очень подходит. Намного проще приводить примеры, основываясь на объектах из реального мира, а не на абстрактных понятиях. Скажем так: объект — это физическая реализация класса.

Методы (methods) — это функции, принадлежащие классу.

Сообщение (message) — это практически тоже самое, что и вызов функций в обычном программировании. В ООП обычно употребляется выражение "послать сообщение" какому-либо объекту. Понятие "сообщение" в ООП можно объяснить с точки зрения основ ООП: мы не можем напрямую изменить состояние объекта и должны как бы послать сообщение объекту, что мы хотим так и так изменить его состояние. Объект сам меняет свое состояние, а мы только его просим об этом посылая сообщения

Пример

Простейшее описание класса и создание его экземпляра. В данном примере мы описываем пустой класс, представляющий будущий игровой мир и в теле программы создаём единственный экземпляр мира.

class CWorld
{
}


int main ()
{
  CWorld world;
}

Рисунок 1 – Простейшее описание класса

О компиляции

Прежде всего, программист с помощью того или иного текстового редактора готовит файлы исходного кода на C/C++. После этого происходит построение программы, в котором можно выделить такие этапы:

  • Компиляцию исходных файлов в файлы объектного кода (с расширением .obj).

  • Компоновку объектных файлов с присоединением необходимых библиотек (в том числе, возможно, динамических), в результате чего получается уже машинный код.

  • Компоновку ресурсов (ресурсы включают в себя битовые матрицы, курсоры, строковые таблицы, пиктограммы и т.п.). Это завершающий этап, на котором формируется конечный ехе-файл, запускаемый на выполнение.

  Компилятор C/C++ генерирует стандартные объектные файлы с расширением .obj. (Их формат определен фирмой Intel и не зависит от конкретной операционной системы.) Файлы эти содержат машинный код, который снабжен дополнительной информацией, позволяющий компоновщику разрешать ссылки между объектными модулями. Так, в начале файла формируются две таблицы: таблица глобальных символов (это имена объектов, определяемых в данном файле, на которые могут ссылаться другие модули программы) и таблица внешних ссылок (имена объектов в других файлах, к которым обращается данный модуль). Пользуясь информацией этих таблиц, компоновщик модифицирует код, подставляя в него соответствующие адреса.

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

C/C++ был задуман как максимально универсальный язык, и потому он не может использовать нестандартный формат объектных файлов. Это сделало бы невозможным, например, создание файлов подпрограмм, которые могли бы включаться в программы, написанные на других языках. Возможность раздельной компиляции обеспечивается в C/C++ применением заголовочных файлов, присоединяемых к компилируемым исходным файлам на этапе препроцессорной обработки. Заголовки содержат прототипы функций, объявления типов и другую информацию, необходимую для раздельной компиляции исходных модулей программы.

Заголовочные файлы (они имеют расширение .h или .hpp) подключаются к компилируемому файлу исходного кода (.с или .срр) с помощью директивы препроцессора #include, за которой следует имя заголовочного файла в кавычках или угловых скобках, например:

#include <stdlib.h>

include "myfile.h"

Препроцессор заменяет директиву #include содержимым указанного файла; после завершения препроцессорной обработки полученный текст передается компилятору, который транслирует его в объектный код.

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

С практической точки зрения раздельная компиляция нужна для сокращения времени компиляции при внесении изменений в код какого-то класса. Раздельная компиляция подразумевает разделение прототипов классов и функций и их реализаций. Соответствие прототипов и реализаций происходит на этапе компоновки объектных файлов. Таким образом, если изменение затронуло реализацию группы классов, в перекомпиляции будут нуждаться только эти классы. Однако последующая компоновка и проверка зависимостей остаётся необходимой.

В С++  раздельная компиляция реализуется путём создания проекта, в который включаются файлы, содержащие реализацию. Обычно, эти файлы имеют расширение «.cpp». При перкомпиляции проекта компилятор проверяет изменения, которые произошли с файлами, включёнными в проект и производит соответствующую компиляцию. Заголовочные файлы (с расширением «.hpp» или «.h») в проект не включаются, но они должны быть включены в каждый файл реализации, в котором используется то, что описано в заголовочных файлах. Типичным примером может служить разделение прототипа класса и реализация его методов. Обычно прототип файла описывается в одноимённом с классом файле .hpp, реализация —  в одноимённом файле .cpp. Следует помнить, что препроцессор не проверяет, сколько раз на этапе препроцессинга файл был включен в программу, поэтому необходимо вручную с помощью условных комментариев контролировать единственность включения (например, этого можно достичь, используя #ifndef - #define, как показано в примере ниже).

Пример. Описание класса CWorld в двух файлах для раздельной компиляции.

//Файл CWorld.hpp

#ifndef CWORLD_HPP
#define CWORLD_HPP
#include "CIObject.hpp"
#include
"CPlayer.hpp"
#define MAXOBJECTS 20
class CWorld
{
  
private:
   unsigned
long time, // общемировое время
             btime;
// время последнего бонуса
     
protected:
   CIObject *objects[MAXOBJECTS];
   
int objectsn;
   
   CPlayer player;
   
  
public:
   CWorld();
   ~CWorld();  
};
#endif

Рисунок 2 – заголовочный файл класса CWorld

//Файл CWorld.cpp

#ifndef CWORLD_CPP
#define CWORLD_CPP
#include "CIObject.hpp"
#
include "CPlayer.hpp"
#
include "CWorld.hpp"
CWorld::CWorld() : player(200,300, 0, 0) // инициализация игрока
{
 objectsn=0;
 time = 0;
 btime = 0;
}

CWorld::~CWorld()
{
 delete [] objects;
}
}

#endif

Рисунок 3 – файл реализации класса CWorld