Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
51
Добавлен:
30.03.2020
Размер:
88.91 Кб
Скачать

Деструктор

Деструктор в рассматриваемом классе можно не реализовывать. Это обусловлено тем обстоятельством, что отсутствуют операции, которые он должен выполнять.

Приведем теперь окончательную реализацию разработанного класса B_1.

//Файл B_1.cpp B_1 :: B_1() : m_(0) { }

B_1 :: B_1(const A& a, int m) : a_(a), m_(m) { }

B_1 :: B_1(const B& rhs) : a_(rhs.a_), m_(rhs.m_) { }

void B_1 :: display() { a_.disply(); cout << “m = ” << m_ << endl; }

Отметим, что класс A оказывается включенным в класс B1 в соответствии с принципом композиции. Приведем законченную диаграмму классов для рассматриваемого примера.

Разработка класса B_2.

Напишем для него заголовочный файл. Обратите внимание на то, что добавлен деструктор.

// Файл B_2.h

class B_2

{

public:

B_2();

B_2(const A& a, int m);

B_2(const B_2_1& rhs); ~B_2(); void display();

private:

A *pa_;

int m_;

};

Перейдем к разработке реализации класса B_2. Отметим ряд важных исходных положений для реализации. При работе с указателями одним из центральных вопросов является вопрос о том, кто «владеет» объектом, на который установлен указатель (указатель pa_). Решение упрощается, если полагать, что права «владения» находятся у агрегатного объекта (объекта класса B_2). Будем предполагать, что в любом своем состоянии объект агрегатного класса содержит объект класса A.

Реализация класса b_2.

// Файл B2.cpp B_2 :: B_2() : pa_(new A), m_(0) { } B_2 :: B_2(const A& a, int m) : pa_(new A(a)), m_(m) { }

B_2 :: B_2(const B_2_1& rhs) : pa_(new A(*rhs.pa_)), m_(rhs.m_) { } B_2 :: ~B_2() { delete pa_; } void B_2 :: display() { pa_->display(); cout << “m = ” << m << endl; }

Обсуждение. В этой реализации класс целое (B_2) «владеет» объектом, на который установлен его указатель pa_. После уничтожения объекта этого класса будет уничтожен и объект его компонента класса A. Можно считать, что классы A и B_2 связаны отношением композиции.

Пример организации классов для лабораторной работы

Класс №1

Свойства

(Класс №1)

Класс №2

Свойства

(Класс №2)

CSpine

(Позвоночник)

Float LeightSpine

(Длинна позвоночника, например – 17)

String NameSpine

(Название позвонка, например - Шейный)

CMammal

(Млекопитающее)

Float WeightMammal

(Вес млекопитающего, например – 25)

CSpine* MammaFeatures

Дополнение.

Возможны следующие варианты организации классов:

а) организуется модули отдельно для класса CSpine и CMammal;

б) организуется общий модуль для указанных классов.

Вариант а) является предпочтительным.

Пример на основе двух классов: Spine и Mammal:

#include "pch.h"

#include <iostream>

#include <string>

using namespace std;

#define _CRT_SECURE_NO_WARNINGS

/*Создаем класс Spine(Позвоночник)*/

class Spine

{

/*Объявляем переменную lengthSpine(Длина позвоночника) типа float и

переменную WallColor(Название позвоночника) типа string c модификатором доступа private */

private:

float lengthSpine;

string nameSpine;

public:

/*Объявляем конструктор по умолчанию*/

Spine()

{

/*Производим отладочную печать работы конструктора по умолчанию и инициализируем переменные lengthSpine и nameSpine */

cout << "Конструктор по умолчанию Spine" << endl;

lengthSpine = 0.6;

nameSpine = "Грудной";

}

/*Объявляем конструктор, который принимает в качестве параметров две переменные:

lengthSpine типа float и nameSpine типа string.

В инициализации конструктора инициализируем переменные lengthSpine и nameSpine полученными значениями */

Spine(float lengthSpine, string nameSpine) : lengthSpine(lengthSpine), nameSpine(nameSpine)

{

/*Производим отладочную печать работы конструктора с параметром*/

cout << "Конструктор c параметрами Spine" << endl;

}

/*Объявляем конструктор копирования Spine, который принимает в качестве параметра объект Spine с именем cpySpine

В инициалиации конструктора копируем поля объекта cpySpine в lengthSpine и nameSpine соответственно скопированным значениями*/

Spine(const Spine& cpySpine) : lengthSpine(cpySpine.lengthSpine), nameSpine(cpySpine.nameSpine)

{

/*Производим отладочную печать работы конструктора копирования*/

cout << "Конструктор копирования Spine" << endl;

}

/*Объявляем перегруженный оператор присваивания*/

Spine& operator=(const Spine &spine)

{

/*Производим отладочную печать работы перегруженного оператора присваивания

Копируем поля объекта cpySpine в lengthSpine и nameSpine соответственно*/

cout << "Перегруженный оператор присваивания Spine" << endl;

this->lengthSpine = spine.lengthSpine;

this->nameSpine = spine.nameSpine;

/*Возвращаем текущий объект*/

return *this;

}

/*Объявляем деструктор*/

~Spine()

{

/*Производим отладочную печать работы деструктора*/

cout << "Деструктор Spine" << endl;

}

/*Объявляем setter для записи значения в private lengthSpine*/

void setLengthSpine(float lengthSpine)

{

this->lengthSpine = lengthSpine;

}

/*Объявляем getter для получения значения из private lengthSpine*/

float getLengthSpine()

{

return lengthSpine;

}

/*Объявляем setter для записи значения в private nameSpine*/

void setNameSpine(string nameSpine)

{

this->nameSpine = nameSpine;

}

/*Объявляем getter для получения значения из private nameSpine*/

string getNameSpine()

{

return nameSpine;

}

/*Метод вывода print полей класса*/

void print()

{

cout << "Длина позвоночника: " << lengthSpine << " м." << endl;

cout << "Название позвоночника: " << nameSpine << endl;;

}

};

/*Создаем класс Mammal(Млекопитающее)*/

class Mammal

{

/*Объявляем переменную weightMammal(Вес млекопитающего) типа float

и объявляем указатель mammalFeatures(Особенности млекопитающего) на класс Spine c модификатором доступа private */

private:

float weightMammal;

Spine* mammalFeatures;

public:

/*Объявляем конструктор по умолчанию*/

Mammal()

{

/*Производим отладочную печать работы конструктора по умолчанию и инициализируем переменную weightMammal значением,

и выделяем память для mammalFeatures */

cout << "Конструктор по умолчанию Mammal" << endl;

weightMammal = 25.5;

mammalFeatures = new Spine[2];

}

/*Объявляем конструктор, который принимает в качестве параметров три переменные:

lengthSpine типа float, nameSpine типа string и weightMammal типа float.

В инициализации конструктора инициализируем переменную weightMammal полученным значением */

Mammal(float lengthSpine, string nameSpine, float weightMammal) : weightMammal(weightMammal)

{

/*Производим отладочную печать работы конструктора с параметрами, выделяем память для mammalFeatures,

передавая в качестве размерности 2 и вызываем setter`ы setLengthSpine и setNameSpine класса Spine,

передавая в качестве параметров переменные lengthSpine и nameSpine соответственно */

cout << "Конструктор с параметром Mammal " << endl;

mammalFeatures = new Spine[1];

mammalFeatures->setLengthSpine(lengthSpine);

mammalFeatures->setNameSpine(nameSpine);

}

/*Объявляем конструктор копирования Mammal, который принимает в качестве параметров объект Mammal

с именем cpyMammal.

В инициализации конструктора инициализируем переменную weightMammal скопированным значением */

Mammal(const Mammal& cpyMammal) : weightMammal(cpyMammal.weightMammal)

{

/*Производим отладочную печать работы конструктора копирования. Выделяем память для mammalFeatures, передавая в качестве размерности 1

Копируем поля объекта cpyMammal в mammalFeatures соответственно*/

cout << "Конструктор копирования Mammal" << endl;

this->mammalFeatures = new Spine[1];

this->mammalFeatures[0] = cpyMammal.mammalFeatures[0];

}

/*Объявляем перегруженный оператор присваивания*/

Mammal& operator=(const Mammal &mammal)

{

/*Производим отладочную печать работы перегруженного оператора присваивания*/

cout << "Перегруженный оператор присваивания Mammal" << endl;

/*Проверка на выделенность памяти. Если выделено-очищаем*/

if (this->mammalFeatures != nullptr)

{

delete[] this->mammalFeatures;

}

/*Выделяем память*/

this->mammalFeatures = new Spine[1];

/*Копируем поля объекта mammal в weightMammal и в цикле mammalFeatures соответственно*/

weightMammal = mammal.weightMammal;

this->mammalFeatures[0] = mammal.mammalFeatures[0];

/*Возвращаем текущий объект*/

return *this;

}

/*Объявляем деструктор*/

~Mammal()

{

/*Производим отладочную печать работы деструктора и освобождаем выделенную память для mammalFeatures*/

cout << "Деструктор Mammal" << endl;

delete[] mammalFeatures;

}

/*Объявляем setter для записи значения в private weightMammal*/

void setWeightMammal(float weightMammal)

{

this->weightMammal = weightMammal;

}

/*Объявляем getter для получения значения из private weightMammal*/

float getWeightMammal()

{

return weightMammal;

}

/*Метод вывода print полей класса*/

void print()

{

/*Вызываем метод print из класса Spine*/

mammalFeatures->print();

cout << "Вес млекопитающего: " << weightMammal << " кг." << endl;

}

};

int main()

{

/*Объявляем переменные lengthSpine и weightMammal типа float и nameSpine типа string*/

float lengthSpine, weightMammal;

string nameSpine;

/*Устанавливаем русский язык*/

system("chcp 1251");

/*Очищаем окно консоли*/

system("cls");

cout << "Введите название позвоночника: ";

/*Считываем переменную nameSpine, введенной с клавиатуры*/

cin >> nameSpine;

cout << "Введите длину позвоночника: ";

/*Считываем переменную lengthSpine, введенной с клавиатуры*/

cin >> lengthSpine;

cout << "Введите вес млекопитающего: ";

/*Считываем переменную weightMammal, введенной с клавиатуры*/

cin >> weightMammal;

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Mammal с именем defaultMammal, который вызывает конструктор по умолчанию*/

Mammal defaultMammal;

/*Выводим на экран получившиеся данные*/

defaultMammal.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Mammal с именем mammalWithUserConstr, который вызывает конструктор с параметрами*/

Mammal mammalWithUserConstr(lengthSpine, nameSpine, weightMammal);

/*Выводим на экран получившиеся данные*/

mammalWithUserConstr.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Mammal с именем cpyMammal, который вызывает конструктор копирования*/

Mammal cpyMammal(mammalWithUserConstr);

/*Выводим на экран получившиеся данные*/

cpyMammal.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Mammal с именем overloadedMammal, который вызывает конструктор по умолчанию*/

Mammal overloadedMammal;

/* Инициализируем экземпляр класса overloadedMammal экземпляром класса mammalWithUserConstr,

в результате этого вызывается перегруженный оператор присваивания */

overloadedMammal = mammalWithUserConstr;

/*Выводим на экран получившиеся данные*/

overloadedMammal.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Spine с именем defaultSpine, который вызовет конструктор по умолчанию*/

Spine defaultSpine;

/*Выводим на экран получившиеся данные*/

defaultSpine.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Spine с именем spineWithUserConstr, который вызовет конструктор с параметрами*/

Spine spineWithUserConstr(lengthSpine, nameSpine);

/*Выводим на экран получившиеся данные*/

spineWithUserConstr.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Spine с именем spineWithUserConstr, который вызовет конструктор копирования*/

Spine cpySpine(spineWithUserConstr);

/*Выводим на экран получившиеся данные*/

cpySpine.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

/*Объявляем экземпляр класса Mammal с именем overloadedSpine, который вызывает конструктор с параметрами*/

Spine overloadedSpine(lengthSpine, nameSpine);

/* Инициализируем экземпляр класса overloadedSpine экземпляром класса defaultSpine,

в результате этого вызывается перегруженный оператор присваивания */

overloadedSpine = defaultSpine;

/*Выводим на экран получившиеся данные*/

overloadedSpine.print();

cout << "----------------------------------------------------------------------------" << "\n"

<< "----------------------------------------------------------------------------" << endl;

}

Соседние файлы в папке Описания лабораторных работ