ЛР1_Классы (1079096), страница 2

Файл №1079096 ЛР1_Классы (Архив готовых лабораторных работ для ИУ) 2 страницаЛР1_Классы (1079096) страница 22018-01-11СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 2)

Пример 1.

В текстовом файле хранится база отдела кадров предприятия. На предприятии 100 сотрудников. Каждая строка файла содержит запись об одном сотруднике. Формат записи: фамилия и инициалы (30 позиций, фамилия должна начинаться с первой позиции), год рождения (5 позиций), оклад (10 позиций). Написать про­грамму, которая по заданной фамилии выводит на экран сведения о сотруднике, подсчитывая средний оклад всех запрошенных сотрудников.

В программе, предложенной для решения задачи, при структурном программировании для хранения сведений об одном сотруднике использовалась бы структура Man:

const int l_name=30;

struct Man {

char name[l_name];

int birth_year;

float pay;

};

Начнем с того, что преобразуем эту структуру в класс, так как мы предполагаем, что наш новый тип будет обладать более сложным поведением, чем просто чте­ние и запись его полей:

class Man {

char name[l_name];

int birth_year;

float pay; };

Замечательно. Это у нас здорово получилось! Все поля класса по умолчанию — закрытые (private). Так что если клиентская функция main() объявит объект Man man, а потом попытается обратиться к какому-либо его полю, например: man.pay = value, то компилятор быстро пресечет это безобразие, отказавшись компилиро­вать программу. Поэтому в состав класса надо добавить методы доступа к его по­лям. Эти методы должны быть общедоступными, или открытыми (public).

Однако предварительно вглядимся внимательнее в определения полей. В решении задачи на языке Си поле name объявлено как статический массив длиной l_name. Это не очень гибкое решение. Мы хотели бы, чтобы наш класс Man можно было использовать в будущем в разных приложениях. Например, если предприятие находится в России, то значение 1_name = 30, по-видимому, всех устроит, если же приложение создается для некой восточной страны, может потребоваться, ска­жем, значение l_name = 200. Решение состоит в использовании динамического мас­сива символов с требуемой длиной. Поэтому заменим поле char name[l_name] на поле char* pName. Сразу возникает вопрос: кто и где будет выделять память под этот массив? Вспомним один из принципов ООП: все объекты должны быть самодостаточными, то есть полностью себя обслуживать.

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

Парным конструктору является другой метод, называемый деструктором, кото­рый автоматически вызывается перед уничтожением объекта. Имя деструктора отличается от имени конструктора только наличием предваряющего символа ~(тильда).

Ясно, что если в конструкторе была выделена динамическая память, то в де­структоре нужно побеспокоиться об ее освобождении. Напомним, что объект, созданный как локальная переменная в некотором блоке { }, уничтожается, ко­гда при выполнении достигнут конец блока. Если же объект создан с помощью операции new, например:

Man* pMan = new Man;

то для его уничтожения применяется операция delete, например: delete pMan. Итак, наш класс принимает следующий вид:

class Man { public:

Man(int I_name = 30) { pName = new char[l_name]: } // конструктор

~Man() { delete [] pName: } // деструктор

private:

char* pName;

int birth_year:

float pay: };

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

Рассмотрим теперь одну важную семантическую деталь: в конструкторе класса параметр l_name имеет значение по умолчанию (30). Если все параметры конст­руктора имеют значения по умолчанию или если конструктор вовсе не имеет па­раметров, он называется конструктором по умолчанию. Зачем понадобилось спе­циальное название для такой разновидности конструктора? Разве это не просто удобство для клиента — передать некоторые значения по умолчанию одному из методов класса? Нет! Конструктор — это особый метод, а конструктор по умол­чанию имеет несколько специальных областей применения.

Во-первых, такой конструктор используется, если компилятор встречает опреде­ление массива объектов, например: Man man[25]. Здесь объявлен массив из 25 объ­ектов типа Man, и каждый объект этого массива создан путем вызова конструкто­ра по умолчанию! Поэтому если вы забудете снабдить класс конструктором по умолчанию, то вы не сможете объявлять массивы объектов этого класса. Исключение представляют классы, в которых нет ни одного конструктора, так как в та­ких ситуациях конструктор по умолчанию создается компилятором.

Вернемся к приведенному выше описанию класса. В нем методы класса опреде­лены как встроенные (inline) функции. При другом способе методы только объявляются внутри класса, а их реализация записывается вне определения класса, как показано ниже:

// Man.h (интерфейс класса)

class Man {

public:

Man(int I_name = 30); // конструктор

~Man(); // деструктор

private:

char* pName;

int birth_year;

float pay;

};

// Man.cpp (реализация класса)

#include "Man.h"

Man::Man(int l_name) { pName = new char[l_name]; }

Man::~Man() { delete [] pName; }

При внешнем определении метода перед его именем указывается имя класса, за которым следует операция доступа к области видимости ::. Выбор способа оп­ределения метода зависит в основном от его размера: короткие методы можно определить как встроенные, что может привести к более эффективному коду. Впрочем, компилятор все равно сам решит, может он сделать метод встроенным или нет.

Продолжим процесс проектирования интерфейса нашего класса. Какие методы нужно добавить в класс? С какими сигнатурами? На этом этапе очень полезно задаться следующим вопросом: какие обязанности должны быть возложены на класс Man?

Первую обязанность мы уже реализовали: объект класса хранит сведения о со­труднике. Чтобы воспользоваться этими сведениями, клиент должен иметь воз­можность получить эти сведения, изменить их и вывести на экран. Кроме этого, для поиска сотрудника желательно иметь возможность сравнивать его имя с за­данным.

Начнем с методов, обеспечивающих доступ к полям класса. Для считывания значений полей добавим методы GetName(), GetBirthYear(), GetPay(). Очевидно, что аргументы здесь не нужны, а возвращаемое значение совпадает с типом поля.

Для записи значений полей добавим методы SetName(), SetBirthYear(), SetPay(). Чтобы определиться с сигнатурой этих методов, надо представить себе, как они будут вызываться клиентом.

Обратите внимание на следующие моменты.

Ввод/вывод кириллицы.. Если вы работаете в интегрированной среде, поддерживающей кодировку символов в стандарте ASCII (например, любой среде на платформе MS-DOS), то проблем с вводом/выводом кириллицы у вас не будет. Проблемы возникают при работе в интегрированной среде на платформе Windows (например, Visual C++ 6.0), поскольку кодировка по стандарту ANSI, принятая в Windows, отличается во второй (национальной) части кодов от кодировки ASCII.

Заголовочные файлы. Стандартная библиотека C++ имеет несколько реализаций. В первоначальной версии библиотеки использовались заголовочные файлы с рас­ширением .h, например <iostream.h>. Если вы работаете с компилятором, который поддерживает версию библиотеки, вошедшую в стандарт языка ISO/IEC 14882 (1998), то заголовочные файлы можно указывать без расширения, например <iostream>. Кроме того, обычно используется директива using namespace std;, так как все имена в стандартной версии библиотеки принадлежат пространству std. В старых версиях библиотеки отсутствуют некоторые очень удобные средства, например не реализован класс string.

Константные методы. Обратите внимание, что заголовки тех методов класса, которые не должны изменять поля класса, снабжены модификатором const после списка параметров. Если вы по ошибке попытаетесь в теле метода что-либо при­своить полю класса, компилятор не позволит вам это сделать. Другое достоинст­во ключевого слова const — оно четко показывает сопровождающему программисту намерения разработчика программы. Например, если обнаружено некорректное поведение приложения и выяснено, что «кто-то» портит одно из полей объекта класса, то сопровождающий программист сразу может исключить из списка подозреваемых методы класса, объявленные как const. Поэтому использование const в объявлениях методов, не изменяющих объект, считается хорошим стилем программирования.

Отладочная печать в конструкторе и деструкторе. Вывод сообщений типа «Constructor is working», «Destructor is working» очень помогает на началь­ном этапе освоения классов. Да и не только на начальном — мы сможем убе­диться в этом, когда столкнемся с проблемой локализации неочевидных ошибок в программе.

СОВЕТ -----------------------------------------------------------------------------------------------------

Вставляйте отладочную печать типа «Здесь был я!» в тела конструкторов и де­структоров, чтобы увидеть, как работают эти невидимки. Использование этого приема особенно полезно при поиске трудно диагностируемых ошибок.

Перегрузка операций

Любая операция, за исключением “::”, “?:”, “.”, “.*”, определенная в C++, может быть перегружена для создан­ного вами класса. Это делается с помощью функций специального вида, назы­ваемых функциями-операциями (операторными функциями). Общий вид такой функции:

возвращаемый_тип operator # (список параметров) { тело функции }

где вместо знака # ставится знак перегружаемой операции.

Функция-операция может быть реализована либо как функция класса, либо как внешняя (обычно дружественная) функция. В первом случае количество пара­метров у функции-операции на единицу меньше, так как первым операндом при этом считается сам объект, вызвавший данную операцию.

Например, покажем два варианта перегрузки операции сложения для класса Point.

Первый вариант — в форме метода класса:

class Point {

double x, у;

public:

//. . .

Point operator +(Point&);

};

Point Point::operator +(Point& p)

{ return Point(x + p.x, у + р.у); }

Второй вариант — в форме внешней глобальной функции, причем функция, как правило, объявляется дружественной классу, чтобы иметь доступ к его закры­тым элементам:

class Point {

double x, у: public: //. . .

friend Point operator +(Point&, Point&);

};

Point operator +(Point& p1, Point& p2) {

return Point(p1.x + p2.x. p1.у + p2.y);

}

Независимо от формы реализации операции “+” мы можем теперь написать:

Point p1(0, 2), р2(-1, 5);

Point рЗ = p1 + р2;

Будет неплохо, если вы будете понимать, что, встретив выражение p1 + р2, компилятор в случае первой формы перегрузки вызовет метод p1.operator +(p2), а в случае второй формы перегрузки — глобальную функцию operator +(pl, р2).

Результатом выполнения данных операторов будет точка рЗ с координатами х = -1, у = 7. Заметим, что для инициализации объекта рЗ будет вызван конструк­тор копирования по умолчанию, но он нас устраивает, поскольку в классе нет полей-указателей. (Подумайте, почему указатели нельзя просто скопировать, чтобы получить копию объекта?)

Если операция может перегружаться как внешней функцией, так и функцией класса, какую из двух форм следует выбирать? Ответ: используйте перегрузку в форме метода класса, если нет каких-либо причин, препятствующих этому. Например, если первый аргумент (левый операнд) относится к одному из базо­вых типов (к примеру, int), то перегрузка операции возможна только в форме внешней функции. (Вспомните, что по умолчанию с помощью указателя this в методы класса передается передается адрес объекта, вызвавшего метод).

Пример 2.

Пример перегрузки операции << для вывода в файл некоторой структуры element.

//overload.cpp - запись структур в файл перегруженной

// операцией <<

#include <iostream>

#include <fstream>

using namespace std;

Характеристики

Тип файла
Документ
Размер
114,5 Kb
Тип материала
Высшее учебное заведение

Список файлов лабораторной работы

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6376
Авторов
на СтудИзбе
309
Средний доход
с одного платного файла
Обучение Подробнее