Форма отчета по лабораторной работе Отчет должен содержать: титульный лист, цель работы, условие задачи, текст программы с комментариями, ручной расчет контрольного примера и результаты решения контрольного примера программой для проверки правильности работы алгоритма, выводы по работе.
Вопросы для самоконтроля
1. Классы и объекты.
2. Статусы доступа полей и методов.
3. Назначение и перегрузка конструкторов.
4. Деструктор класса.
3. Лабораторная работа № 3. Изучение перегрузки стандартных операций в языке Си++
Цель и задачи работы, требования к результатам ее выполнения
Цель работы состоит в овладении навыками разработки программ на языке Си++, использующих перегрузку стандартных операций. Для достижения цели необходимо выполнить следующие задачи:
- изучить необходимые учебные материалы, посвященные перегрузке стандартных операций в языке Си++ [1, 3];
- разработать программу на языке Си++ для решения заданного варианта задания;
- отладить программы;
- выполнить решение контрольного примера с помощью программы и ручной расчет контрольного примера;
- подготовить отчет по лабораторной работе.
Краткая характеристика объекта изучения
Перегрузка операций в языке Си++ это возможность распространения действия стандартных операций на операнды, для которых эти операции первоначально не предназначались [1, 3]. Это возможно, если хотя бы один из операндов является объектом класса, для этого создается специальная, так называемая, оператор- функция, которая может быть как членом класса, так и функцией, не принадлежащей классу.
Формат определения оператор- функции имеет вид:
<тип_возвращаемого_значения>
operator <знак_операции>
(спецификация_параметров)
{
операторы_тела_функции
}
Существует три способа перегрузки [3]:
- оператор-функция определяется как функция, не принадлежащая классу;
- оператор-функция определяется как функция класса;
- оператор-функция определяется как дружественная функция класса.
Особенности перегрузки операций:
- можно перегружать только стандартные операции, например, нельзя перегрузить операцию ‘**’ (возведение в степень в языке Фортран, отсутствует в Си++);
- не допускают перегрузки операции: ‘.’, ‘.*’, ‘?:’, ‘::’, ‘sizeof’, ‘#’, ‘##’;
- при перегрузке сохраняется арность операций (унарная операция остается унарной, а бинарная – бинарной);
- бинарная операция перегружается либо как функция, не принадлежащая классу с двумя параметрами, один обязательно объект (ссылка на объект) класса, или как функция класса с одним параметром, первым операндом операции выступает объект класса, для которого вызывается функция;
- бинарные операции ‘=‘, ‘[]’, ‘->’ должны обязательно определяться как компонентные функции класса;
- унарная операция перегружается либо как функция, не принадлежащая классу с одним параметром - объектом (ссылкой на объект) класса, или как функция класса без параметров, операндом операции выступает объект класса, для которого вызывается функция.
Задачи и порядок выполнения работы
Студент в работе создает класс и необходимые оператор- функции для перегрузки заданных в своем варианте операций. Особое внимание обратить на способы перегрузки унарных и бинарных операций и параметры оператор- функций для этих операций, когда оператор функция является членом класса и когда не является. Знать те случаи, когда оператор функция должна быть обязательно членом класса и случаи, когда оператор- функция обязательно не принадлежит классу. При защите работы необходимо обосновать выбор способа определения оператор- функции – внутри класса или вне его. При необходимости студент выполняет ручной расчет для проверки работы программы для задачи небольшой размерности. Результаты работы программы, ручного расчета представляются в отчете.
Условие задачи:
Дан класс (например, с именем Vector), задающий вектор размерности n. Поля класса: указатель на массив, задающий вектор (тип элемента double), массив должен создаваться динамически; число элементов (размерность) вектора (тип int). Класс включает: конструктор без параметров, задающий пустой вектор (число элементов равно 0); конструктор, создающий объект вектор на основе обычного одномерного массива размерности n; деструктор.
Необходимо перегрузить операции и продемонстрировать их работу. Перегрузить операцию [] (обращение к элементу вектора по индексу), операцию = (копирование вектора или создание копии вектора), операцию * (умножение числа на вектора), на выходе вектор такой же размерности, каждый элемент которого равен произведению соответствующего элемента исходного вектора на число.
Пример выполнения работы
Для решения задачи в среде Microsoft Visual Studio 2013 было создано стандартное консольное приложение (проект типа Win32 Console Application). Исходные коды основного файла проекта (файла с расширением .cpp) и файла stdafx.h приведены ниже.
Листинг программы с комментариями:
// Project3.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
class Vector // Класс- вектор
{
double *p; // Указатель на массив (вектор)
int n; // Размерность вектора (число элементов) массива
public:
Vector(double *p, int n) // Коструктор на входе массив, задающий вектор
{
this->n = n; // Задаем число элементов
this->p = new double[n]; // Выделяем память
for (int i = 0; i<n; i++) this->p[i] = p[i]; // Копируем один массив в другой
}
void print() // Печать вектора (массива)
{
cout << "\n";
for (int i = 0; i<n; i++)
cout << p[i] << " ";
}
Vector() { p = 0; n = 0; } // Конструктор без параметров, задает "пустой" объект
double& operator[](int index) // Оператор- функция (перегрузка операции
// обращения к элементу)
{
return p[index];
}
Vector & operator =(Vector& v2) // Оператор- функция копирования объекта
{
n = v2.n;
p = new double[n];
for (int i = 0; i<n; i++) p[i] = v2.p[i];
return *this;
}
~Vector() // Деструктор
{
if (n>0) delete[] p; // Освобождаем память
}
friend Vector & operator *(double x, Vector& v2); // Дружественная функция,
// определенная вне класса
};
// Умножение числа на вектор (первый операнд не объект класса,
// функция обязательно определяется вне класса)
Vector & operator *(double x, Vector& v2) // Оператор- функция вне класса
{
double *p = new double[v2.n]; // Создаем новый массив
for (int i = 0; i<v2.n; i++) p[i] = x*v2.p[i]; // Заполняем массив
Vector *pV = new Vector(p, v2.n); // Создаем новый объект на основе массива
delete[] p; // Освобождаем массив
return *pV; // Возвращаем ссылку на объект
}
int _tmain(int argc, _TCHAR* argv[])
{
double m1[] = { 1, 2, 3, 4.5, 7 };
Vector V1(m1, 5); // Создаем объект
V1.print(); // Печать объекта
cout << "\n";
for (int i = 0; i<5; i++)
cout << V1[i] << " "; // Пример обращения к операции []
V1[0] = 10.6; // Пример обращения к операции []
V1.print(); // Печать объекта
Vector V2; // Новый объект (вначале "пустой")
V2 = 100 * V1; // Пример выполнение перегруженной операции *
// V2=operator *(100, V1);
V2.print(); // Печать полученного объекта
system("pause"); // Останавливаем программу до нажатия любой клавиши
return 0;
}
// stdafx.h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются, но
// не часто изменяются
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: Установите здесь ссылки на дополнительные заголовки, требующиеся для программы
#include <stdlib.h>
#include <iostream>
using namespace std;
|