Материал: ЛР 8 Информатика 2 сем 2020

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

9Лабораторная работа №8. Классы и объекты

9.1Цели и задачи работы:

Цель данной лабораторной работы — научиться работать с классами. Задача данной лабораторной работы — выполнить выданные типовые

задания (1 задачу).

9.2Теоретическая часть

Вязыке «C++» пользовательские типы данных могут содержать не только стандартные типы данных, как структуры, но и собственные функции. Созданный пользователем тип данных в терминах языка «C++» называется «классом», данные стандартных типов, входящие в него, - «свойствами класса», а входящие в него функции – «методами класса». Созданная переменная этого типа (экземпляр) класса называется «объектом».

Вранее упомянутый тип данных «вектор» можно добавить, например, функцию «GetLength()» для вычисления длины вектора.

struct MyVector

{

float x; float y;

// Метод GetLength() класса MyVector float GetLength()

{

//sqrt - функция для вычисления квадратного корня,

//описанная в заголовочном файле <math.h>

return sqrt(x * x + y * y);

}

};

Для вызова методов класса для его объектов используется оператор «.»:

MyVector vect; // Создаём вектор vect.x = 3;

vect.y = 4;

// Вычисляем его длину

float len = vect.GetLength();

// В переменную len будет записано значение 5

143

А для обращения обращаемся к методам и свойствам класса по указателю на его объект используется оператор «->»:

MyVector *pointer = new MyVector; // Создаём вектор pointer->x = 3;

pointer->y = 4;

// Вычисляем его длину

float len = pointer->GetLength();

// В переменную len будет записано значение 5

delete pointer;

При необходимости защитить свойства объекта класса от непосредственного изменения, т.е. что бы к ним нельзя было обращаться «напрямую», используя операторы «.» и «->», перед ними можно поставить спецификатор доступа «private:». Или сам класс можно объявить с использованием ключевого слова «class». А перед свойствами и методами, к которым допускается обращение через «.» и «->» тогда нужно поставить спецификатор доступа «public:».

class MyClass

{

int a;// К свойству a напрямую обращаться нельзя,

public:

//для задания его значения нужно вызвать метод: void setvalue(int val)

{

a = val;

}

//для получения его значения нужно вызвать метод: int getvalue()

{

return a;

}

}

144

Как вы уже, наверное, заметили, в методы не нужно передавать как аргументы ссылки или указатели на экземпляры класса, чтобы получить к ним доступ. Мы не прописываем соответствующие параметры в сигнатуре методов, и не передаѐм соответствующие аргументы при их вызовах.

Когда компилятор встречает в программе вызов метода класса через «.» или «->», перед которыми записан объект класса, или, соответственно, указатель на него, то он передаѐт в него первым аргументом (параметром) константный указатель на этот объект. Делает компилятор это автоматичски и неявно (скрыто). Такой указатель, хранящий адрес объекта класса, называется «this». При реализации метода класса указатель this можно не прописывать, компилятор его подставит сам. Например, такие записи эквивалентны:

void setvalue(int val)

void setvalue(int val)

{

{

this->a = val;

a = val;

}

}

А следующие записи – нет:

 

void setvalue(int a)

void setvalue(int a)

{

{

this->a = val;

a = a;

}

}

В первом случае всѐ будет работать, как и ожидалось. А во втором – ничего не произойдѐт из-за перекрытия имѐн переменных. Компилятор будет под «a» понимать исключительно параметр метода setvalue, как внутренней области видимости. Такие ситуации рекомендуется избегать, давая разные названия свойствам классов и параметрам их методов.

Разберѐм ещѐ такой случай:

struct Dog

{

void voice()

{

std::cout<<"Gav!";

}

};

145

void main()

{

Dog *myDog = nullptr; myDog->voice();

}

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

Теперь рассмотрим специальные методы для классов: «конструктор» и «деструктор», вызываемые автоматически при создании и при удалении объекта класса соответственно.

Конструктор – функция, предназначенная для инициализации объектов класса автоматически при создании. Для примера рассмотрим класс date:

class date

{

// объявление свойств класса unsigned int day, month, year;

public:

//объявление метода для инициализации свойств класса void set(unsigned int, unsigned int, unsigned int);

//(реализация здесь не приведена)

//объявление метода для получения значений свойств void get(unsigned int&, unsigned int&, unsigned int&);

//(реализация здесь не приведена)

};

...

// внутри main():

date d; // Создание объекта класса

unsigned int day, month, year;

d.get(day, month, year); // Получение значений его свойств

146

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

class date

{

...

public:

...

// объявление конструктора

void date(unsigned int, unsigned int, unsigned int); // (реализация здесь не приведена)

};

...

// внутри main():

date d(1, 2, 3); // Создание и инициализация объекта класса // Теперь создать объект класса, не инициализировав его свойства невозможно

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

Конструктор обеспечивает объектам класса надлежащую инициализацию, но для многих типов данных также требуется обратное действие (например, если класс использует динамическую память). Деструктор обеспечивает соответствующую очистку объектов указанного типа. Имя деструктора представляет собой имя класса с предшествующим ему знаком «~» (тильда).

// Тип данных «целочисленный массив» class Massiv

{

unsigned int quantity; // Количество данных int *data; // Указатель на данные

Massiv(unsigned int size)

{

quantity = size; // Запоминаем размер массива data = new int[quantity]; // Выделяем память

};

147

Источник: https://studfile.net/preview/16421898/