- •Классы и объекты
- •Введение
- •Лабораторная работа № 1. Структура-пара
- •Выполнение лабораторной работы
- •Методические указания к выполнению лабораторной работы
- •XXX yyy; // скалярная переменная
- •Vl, v2[20]; // скалярная переменная и массив
- •Int _tmain(int argc, _tchar* argv[])
- •X.Read();
- •X.Display(); // вывод полей на экран
- •Лабораторная работа № 2. Структуры и классы
- •Выполнение лабораторной работы
- •Методические указания к выполнению лабораторной работы
- •Int getDigitByPosition(p_number V,int pos) {
- •Int transferTo10(p_number V) {
- •Int p_number_class::getDigitByPosition(int pos) {
- •Int p_number_class::transferTo10() {
- •Void p_number_class::transferFrom10(int numb) {
- •Int main(int argc, char* argv[])
- •Библиографический список
Выполнение лабораторной работы
Для выполнения работы необходимо:
формализовать задачу;
составить описание структуры;
составить алгоритм для каждого метода, описанного в структуре, и определить все методы;
создать объекты описанного типа;
разработать набор тестов, на которых будет проверяться программа;
продемонстрировать работу программы на наборе тестов;
оформить работу и отчитаться по ней.
Методические указания к выполнению лабораторной работы
Задание
Поле first – целое число; поле second – целое число. Реализовать метод nod() – вычисление наибольшего общего делителя.
Выполнение
Помимо определения новых операций с помощью конструкции подпрограммы, в объектно-ориентированных языках программирования можно определить и новый тип данных посредством конструкции класса. Класс – это структурированный тип, образованный на основе уже существующих типов. В этом смысле класс является расширением понятия записи или структуры.
Описание класса. Класс можно определить с помощью конструкции:
тип_класса имя_класса { компоненты класса };
В этом определении:
тип класса – одно из служебных слов class или struct;
имя класса – идентификатор;
компоненты класса – определения и объявления данных и принадлежащих классу методов.
Имя класса является по умолчанию именем типа объектов. Данные – это поля объекта, образующие его структуру. Значения полей определяют состояние объекта. Методами класса определяются операции над объектами класса.
Класс без полей и без методов называется пустым классом. Элементы класса типа struct по умолчанию открыты и доступны в других частях программы. Члены класса class по умолчанию закрыты и недоступны вне данного класса. Доступ к содержимому класса задается спецификаторами доступа, которые обозначаются ключевыми словами public и private. Ключевое слово public объявляет элемент класса доступным вне класса, а ключевое слово private закрывает доступ снаружи. После ключевого слова требуется поставить знак «:» (двоеточие).
И в классе, и в структуре можно написать столько спецификаторов public и private, сколько необходимо, и в том порядке, в каком требуется. Очередной спецификатор действует до следующего. Допускается индивидуально объявлять каждый элемент класса либо открытым, либо закрытым. Открытая часть класса называется интерфейсом. Сокрытие информации о внутренней структуре – это один из принципов объектно-ориентированного программирования, так называемая инкапсуляция. Примеры объявлений классов приведены в листинге 1.1.
Листинг 1.1. Примеры объявлений классов
class Null Type {}; // пустой класс
struct Empty {}; // пустой класс
struct Pair
{ int first; double second; }; // только поля - открыты
struct date // и поля и методы - открыты
{ int month,day,year; // поля: месяц, день, год
void set(int d,int m,int у); // метод - установить дату
void get(int Sd,int Sm,int &y); // метод - получить дату
void next(); // метод - установить следующую дату
void print(); // метод - показать дату
};
struct Money{
void Add(const long &r); // методы - открыты
void Display();
private:
long Rubls; // поле - закрыто
};
class Fraction{ int num; int denum;// поля - закрыты
public:
void reduce(); // метод - открыт
};
class XXX{ int yyy(); // метод - закрыт
public:
int fff(int t); // метод - открыт
int RRR; // поле - открыто
};
class Library // только открытые методы
{ public: void furiction();
public: int Fnction(int); };
Для задачи описание класса выглядит следующим образом:
struct Para {
int first; // первое число
int second; // второе число
void read(); // метод ввода значений для полей
void display(); // метод вывода значений полей на экран
void init(int f,int s);// метод, присваивающий полям значения
int nod(); // метод расчёта наибольшего общего делителя для полей
};
Определение методов класса. Методы класса имеют неограниченный доступ ко всем элементам класса независимо ни от порядка объявления элементов класса, ни от спецификаторов доступа. Методы могут определяться как внутри класса, так и вне его. Определение метода внутри класса не отличается от определения обычной функции. Метод, определенный внутри класса, считается по умолчанию встроенной функцией (inline).
Если метод определяется вне класса, то принадлежность метода классу указывается префиксом-именем класса. В классе присутствует только прототип. Метод, определенный вне класса, по умолчанию не считается inline-функцией. Методы могут быть перегружены и могут принимать аргументы по умолчанию. Аргументом и/или возвращаемым значением метода может быть объект того же класса, и такие объекты разрешено объявлять внутри метода.
Фактически левым аргументом метода является объект, для которого этот метод вызывается, например:
time t; t.settime(12,54);
Метод неявно получает в качестве аргумента указатель на объект, для которого он вызван. Этот указатель обозначается зарезервированным словом this и может использоваться в теле метода. Через него же разумно осуществлять доступ к полям и методам класса в случае неоднозначности (совпадение имен).
this->Summa
Запись *this представляет собой значение текущего объекта. Часто это значение используется для возврата значения определяемого класса.
Методы могут быть перегружены. Перегрузка методов – это одно из проявлений принципа полиморфизма в объектно-ориентированном программировании.
Для ввода значений нового типа обычно реализуется метод Read(). В простейшем виде выполняется заполнение полей нового класса из стандартного потока ввода cin с клавиатуры. В методе перед вводом каждого значения можно вывести подсказку-приглашение, объясняющую очередность набора. Передаваемые значения обычно проверяются на допустимость.
Для вывода значений нового типа реализуется метод Display(). В самом простом случае он представляет собой вывод из полей нового класса на экран – в стандартный поток cout. Метод вывода обычно реализуется как константный (см. листинг 1.2).
Листинг 1.2. Определение методов
class time {
public:
void settime(int h, int m, int s = 0) // определение внутри класса
{ hours = h; minutes = m; seconds = s;
}
void settime(const time &t); // метод перегружен
time nexthour(); // возврат определяемого типа
time addhours(const time &t); // параметр определяемого типа
void Display() const; // вывод - константный метод
void time::Read(); // ввод полей
private: // закрытые поля int hours, minutes, seconds;
};
void time::Display() const // определение вне класса константного метода
{ cout << hours << "." << minutes << "." << seconds; }
void time::Read() // ввод полей
{ h: cout << "Hours : "; cin >> hours;
if (hours > 23) // простая проверка
goto h;
cout << "Minutes: "; cin >> minutes; // без проверки
seconds =0; //не вводится
}
void time::settime(const time &t) // определение вне класса
{ hours = t.hours; mjnutes = t.minutes; seconds = t.seconds; }
time time::addhours(const time &t) // параметр определяемого типа
{ time r = *this; // использование this
r.hours += t.hours; r.hours%=24;
return r; // возврат определяемого типа
}
time time::nexthour()
{ hours++; hours%=24;
return *this; // возврат текущего объекта
}
Для задачи определяем все методы как внешние:
void Para::init(int f,int s) // метод присвоения полям значений
{ first = f;
second = s; }
void Para::display() // метод вывода полей на экран
{ cout << “first: ” << first << “\n second: “ << second; }
void Para::read() // метод ввода полей с клавиатуры
{ cout << “first: ”; cin >> first;
cout << " second: "; cin >> second;
}
int Para::nod() // метод расчёта наибольшего общего делителя
{ int a = first;
Int b = second;
int remainder = 0;
do {
remainder = a % b;
a = b;
b = remainder;
}
while (remainder != 0);
return a;
}
Создание объектов класса и использование объектов класса. Имея определение класса, можно объявлять переменные типа «имя_класса». Переменная класса называется объектом, или экземпляром класса. Класс объявляется один раз, а вот объектов можно создать столько, сколько необходимо. Объекты объявляются аналогично переменным встроенного типа:
имя_класса имя_объекта; // скалярный объект
имя_класса *имя_объекта; // указатель
имя_класса имя_объекта[количество]; // массив
При объявлении переменных можно задавать ключевые слова class и struct:
class имя_класса имя_объекта; // скалярный объект
class имя_класса *имя_объекта; // указатель
struct имя_класса имя_объекта[количество]; // массив
Разрешается совмещать определение класса и объявление переменной:
class имя_класса { члены_класса } имя_объекта; // объект
class имя_класса { члены_класса } *имя_объекта; // указатель
struct имя_класса { члены_класса } имя_объекта[количество]; // массив
Эти переменные получают тип «имя_класса». Тогда в дальнейшем можно объявлять переменные без записи определения класса и без служебных слов class или struct, как показано выше. Объявленные переменные подчиняются правилам видимости, как и переменные встроенных типов, и время их жизни зависит от места объявления.
Следующие переменные могут быть объявлены для приведенных в листинге 1.1 классов:
NullType a, *pb; // скалярная переменная и указатель
Empty d[10]; // массив
date *pd; // указатель
class Money t; // скалярная переменная
class Money *p; // указатель
class Money m[100]; // массив
