Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по программированию ПМФ 2011.doc
Скачиваний:
11
Добавлен:
03.11.2018
Размер:
326.14 Кб
Скачать

Лабораторная работа №6. Основы объектно-ориентированного программирования.

6.1 Цели и постановка задачи

Цель: Познакомиться с основами объектно-ориентированного программирования на примере простейшей структуры классов.

Задание:

  1. Используя наследование, полиморфизм, инкапсуляцию и композицию написать структуру классов заданного варианта (термины объясняются ниже).

  2. Реализовать виртуальные методы сохранения и загрузки из файла, а так же оператор сравнения объектов на равенство (operator==).

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

6.2. Требования к коду программы

Структура исходного кода при определении классов, подчиняется тем же правилам, что и при определении функций. То есть в *.h – файле описывается заголовок класса (у функции это было объявление функции), а в *.cpp – файле описывается реализация класса (также, как реализация функции). Принято каждый отдельный класс описывать в отдельных файлах.

Кроме того, в Microsoft Visual Studio 2005 есть и свои (впрочем, необязательные) требования к оформлению исходного текста объектно-ориентированной программы. Если, например файл называется «Book.*» то класс должен носить название «CBook» », то есть к их названию прибавляется «C» (class). Члены класса (переменные или другие внутренние объекты) принято называть, например, «mPageCount» или «mAuthor», то есть к их названию прибавляется «m» (member). В случае если член является указателем принято называть его «mpText», то есть с добавлением «mp» (member pointer).

6.3. Некоторые основные понятия объектно-ориентированного программирования

Объект (переменная) – экземпляр некого класса (типа данных).

Класс – особый тип данных, определяемый программистом как структура вложенных данных с методами (функциями) обработки их. Класс обладает следующими особенностями:

  1. Инкапсуляция – сокрытие данных объекта (экземпляра класса) от всех, кроме строго определённого набора функций (методов класса) для защиты данных от некорректного использования.

  2. Наследование – способность повторять признаки (набор данных и методы их обработки) других классов (классов-предков), дополняя их своими.

  3. Полиморфизм – способность оперировать в наследуемых классах с данными и методами их обработки классов-предков любого уровня наследования.

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

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

1. Обычные – методы, доступные только из объекта и данные объекта им так же доступны.

1. Статические (static) – методы, доступные как из объекта, так и из класса (даже при отсутствии объектов этого класса). Для них недоступны данные объекта их класса. Фактически это функции, описанные в namespace класса.

3. Перегруженные – обычные методы с одинаковыми именами, но разным набором принимаемых параметров.

4. Виртуальные (virtual) – полиморфные методы, которые способны оперировать с данными любого уровня наследования класса.

5. Абстрактные ( = 0 ) – методы, которые будут определены в предке, но являются неопределенными в настоящем классе.

6. Встроенные (inline) – также как и встроенные функции, методы могут быть встроенными, т.е. фактически они не вызываются, а соответствующий код вставляется в текст программы – поэтому, они быстрее обычных методов. Эти функции должны иметь реализация прямо в *.h файле!

В классе всегда существуют как минимум 2 метода. Первый является статическим конструктором объектов по умолчанию, он вызывается каждый раз, когда создается объект данного класса без параметров. Второй является динамическим деструктором, он вызывается при удалении объекта из памяти. Их имена совпадают с именем класса, только у деструктора в начале добавляется волна «~». Параметров они не имеют. Их можно переопределять. Можно создавать конструкторы с параметрами, как у обычных функций, и их число не ограничено.

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

Рассмотрим структуру некоторой системы классов, иллюстрирующую различные введённые выше понятия:

/**

@file Book.h

@remark Описание класса CBook

*/

#pragma once

class CBook // название класса

{

private: // область видимости только внутри класса

int mPageCount; // член класса (внутренние данные)

public: // область видемости доступная внешне

CBook(void); // конструктор класса

~CBook(void); // дейструктор класса

void learning(); // обычный метод

static void getBook(); // статический метод

virtual int mainPageIndex(); // виртуальный метод

};

/**

@file Book.cpp

@remark Реализация класса CBook

*/

#include "StdAfx.h"

#include "Book.h"

CBook::CBook(void)

{

mPageCount = 0; // при создании объекта книги у него будет 0 страниц

}

CBook::~CBook(void)

{

// выполняет действия при уничтожении объекта

}

void CBook::learning() //обычный метод

{

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

mPageCount = mainPageIndex(); // вызов виртуального метода

CBook::getBook(); // вызов статического класса

}

void CBook::getBook() // статический метод

{

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

}

int CBook::mainPageIndex() // виртуальный метод

{

return mPageCount + 1;

}

/**

@file Student.h

@remark Описание класса CStudent

*/

#pragma once

#include "Book.h"

class CStudent

{

private:

CBook * mpBooks; // композиция (один студен имеет массив книг)

int mBookCount; // содержит количество книг

public:

CStudent(void);

public:

~CStudent(void);

virtual void execute();

// метод виртуальный, посему будет перекрыт в наследуемом классе

virtual char * diplomeTheme() = 0;

// абстрактный метод, он должен быть всегда виртуальным

inline int getBookCount(){ // встроенная функция

// возвращает количество книг

return mBookCount; // инкапсуляция - работа с данными через методы

}

};

/**

@file Student.cpp

@remark Реализация класса CStudent

*/

#include "StdAfx.h"

#include "Student.h"

CStudent::CStudent(void)

{

mBookCount = 4; // например 4 книги есть у любого студента!

mpBooks = new CBook[mBookCount]; // создаем динамический массив

}

CStudent::~CStudent(void)

{

if (mpBooks)

delete[] mpBooks;

// студент сдает книги в библиотеку после окончания вуза, как правило!

}

void CStudent::execute()

{

// сдача экзамена

}

/**

@file Diplomer.h

@remark Описание класса CDiplomer

*/

#pragma once

#include "Student.h"

class CDiplomer : public CStudent // публичное наследование от студента

{

public:

CDiplomer(void);

public:

~CDiplomer(void);

virtual void execute();

// метод виртуальный, перекрыт в предке

virtual char * diplomeTheme();

// абстрактный метод предка будет определен в его потомке, т.е. здесь

};

/**

@file Diplomer.cpp

@remark Реализация класса CDiplomer

*/

#include "StdAfx.h"

#include "Diplomer.h"

CDiplomer::CDiplomer(void) : CStudent() // выполняется конструктор предка

{

}

CDiplomer::~CDiplomer(void)

{

}

void CDiplomer::execute()

{

CStudent::execute(); // выполнение предка - сдача экзамена

// но помимо этого дипломник еще и диплом защищает

}

char * CDiplomer::diplomeTheme()

{

return "Вот такая тема";

}

/**

@file Main.h

@remark Код главной процедуры

*/

#include "Diplomer.h"

#include "Student.h"

#include "Book.h"

int main(int argc, char* argv[])

{

// статическое создание объекта

CBook book; // объявили экзымпляр класса (объекта)

book.learning(); // вызов метода объекта

// динамическое создание объекта

CStudent * student = new CDiplomer();

// на самом деле студент является тут дипломником

student->execute();

// поэтому этот метод быдет защищать диплом помомо сдачи экзаменов

delete student; // динамически созданный объект больше не нужен

return 0;

}