Лабораторные работы МИРЭА 2014 (1017113), страница 8
Текст из файла (страница 8)
int a;
int b;
int f1(int x,int y)/* метод класса*/
{
return (x-y);
}
};
int main()
{
system("chcp 1251");
cout<<"Здравствуй, мир!";
A min; //создание экземпляров классов А,В
min.a=10; // Работа с элементами класса А из секции public
min.b=20;
int x1=min.f1(min.a,min.b);
cout<<"\nx1="<<x1;
getch();
}
Рис.10 Результат работы программы Пример_1
Пример_2: Создадим класс, членами которого будут изделия, состоящие из деталей и их стоимостей, а также методы, первый из которых присваивает значения изделию и детали, а также их стоимости через свои параметры, а второй выводит на экран значения, присвоенные первым методом.
#include <iostream.h> //for cout
#include <conio.h> // for _getch()
class produce //начало определения класса
{
private:
// поля класса
int modelnumber; // номер изделия
int partnumber; // номер детали
float cost; // стоимость детали
public:
// установка данных с помощью метода
// присваивает данным класса значения своих параметров
void setpart(int mn, int pn, float c)
{
modelnumber=mn;
partnumber=pn;
cost=c;
}
void show() // вывод данных
{
cout<<"\nThe Number of the Model is "<<modelnumber;
cout<<"\nThe Number of the Part is "<<partnumber;
cout<<"\nThe Number of the Cost is "<<cost;
}
};//конец описания класса
// обработка класса в головной программе
int main()
{
produce izd;// определение объекта мз класса (экземпляр класса)
izd.setpart(100,200,250.5);// вызов метода класса
izd.show();// вывод данных
getch();
}
Рис.1. Результат работы программы Пример_2
Обратите внимание, что когда вы создаете переменную типа класса, т.е. экземпляр класса (например, A min;, где min – это экземпляр класса), то для этого экземпляра никакой памяти не выделяется. А компилятор все-таки размещает этот экземпляр где-то в памяти. Почему?
Среди исполнения приложений в Си++ выделяют два вида памяти: статическую и динамическую. Последняя носит название «куча» (heap). Куча может быть управляемой и неуправляемой. Если компилятор способен определить размер памяти под объявленную переменную, то он выделяет для нее место в статической памяти (например, под переменную типа int из 10 элементов он выделит 40 байтов). Если компилятор не в состоянии определить размер памяти под объявленную переменную, то он потребует от программиста поместить такую переменную в куче – в динамической памяти. Кстати, если программист сам хочет работать с динамической памятью (даже когда компилятор может поместить переменную в статистической памяти), то язык это ему не позволяет. Для простых переменных при этом используются:
-
Функция malloc(), которая выделяет область памяти в динамической области и возвращает указатель на эту область.
-
Функция free(), которая освобождает занятую переменной область и передает освобожденную память в общее пользование.
Если же работа происходит с объектами, то здесь используются операторы new – аналог malloc(), и delete – аналог free().
Указанные функции и аналогичные им операторы работают с неуправляемой кучей. С управляемой кучей работает утилита gcnew и нет необходимости освобождать самому
память от объекта, поскольку в этом случае работает так называемая автоматическая сборка мусора: когда объект становится ненужным, память от него освобождается.
Но приведем пример этой же программы (пример_1), в которой используется (по нашему желанию) динамическая память:
В данном случае оператор new размещает объект в куче, выдает адрес этого объекта, а конструктор инициализирует объект.
Пример_3: //KIIUT.cpp: главный файл проекта.
#include <iostream.h> //for cout
#include <conio.h> // for _getch()
class A
{
protected:
int x;
int y;
public:
int a;
int b;
int f1(int x,int y)
{
return (x-y);
}
};
int main()
{
system("chcp 1251");
cout<<"Здравствуй, мир!";
A *min=(A *) new A();
min->a=10;
min->b=20;
int x1=min->f1(min->a,min->b);
cout<<"\nx1="<<x1;
getch();
delete min;
}
Рис.2. Результат работы программы Пример_3
Конструкторы и деструкторы класса.
Конструктор класса.
Конструктор класса тоже член класса, но специфический – это метод с таким же именем, что и класс. Такие методы не имеют право возвращать какие-либо значения: если вы написали в конструкторе оператор return, компилятор выдаст ошибку. Конструктор выполняет различные задачи и не виден вам, как программисту. Даже если вы сами не писали его текст, конструктор по умолчанию всегда присутствует в классе, ибо основная его задача – создавать в памяти экземпляр класса (т.е. как бы по проекту (классу) построить дом (экземпляр класса)). В этом случае конструктор берется из общего прародителя классов – класса Object, в котором он имеется.
Вторая задача конструктора – придавать всем членам-данным класса начальные значения. Если вы сами не построили конструктор, который станет инициализировать члены-данные вашего класса вашими же значениями, то этим данным невидимый для вас конструктор (конструктор по умолчанию) придаст свои, принятые в системе для данного типа величин значения (например, данные типа int получат нулевые значения и т.д.). В примере 4 приведен пример класса с конструктором, созданным для инициализации членов-данных класса теми значениями, которые задаст пользователь класса при работе с ним.
Пример_4:
#include <iostream.h> //for cout
#include <conio.h> // for _getch()
class Date
{
public:
/*Это члены-данные класса.
С ними будут работать функции-члены класса:get...и set... */
int month;
int day;
int year;
Date (int dy,int mn, int yr) //конструктор класса
{
/*члены-данные month, day, year будут принимать значения,
которые поступят в конструктор как в функцию при его
использовании где-нибудь в приложении*/
day=dy;
month=mn;
year=yr;
}
int getMonth() const;
/*Функция getMonth() объявлена с атрибутом const - может
данные только поставлять, не изменяя их (read-only),
а функция SetMonth() не имеет квалификатора const
и поэтому данные внутри себя может изменять: виды функций
определены вне класса */
void setMonth(int mn);
int getDay();
void setDay(int dy);
int getYear();
void setYear(int yr);
~Date(){ }//деструктор класса
}; // конец описания класса
/*создание функций (вне класса, поэтому надо указывать
имя класса, для которого эти функции создаются)*/
int Date::getMonth() const
{return month; } //Функция ничего не изменяет
void Date::setMonth(int mn)
{month=mn;} //Функция изменяет член-данное класса
int Date::getDay()
{return Date::day;}
void Date::setDay(int dy)
{day=dy;}
int Date::getYear()
{return Date::year; }
void Date::setYear(int yr)
{Date::year=yr;}
int main() // Работа с созданным классом
{
/*Здесь с помощью конструктора в экземпляре класса
(экземпляр с именем MyDate) устанавливаются заданные
пользователем значения:*/
Date Mydate(21,1,2010);
int d,m,y;
d=Mydate.getDay(); //d=21
m=Mydate.getMonth(); //m=3
y=Mydate.getYear(); //y=2007
cout<<"\nd=" <<d << " m=" <<m << " y="<<y;
Date BirthDate(1,12,1938);
/*Изменить значение месяца на значение 4 в экземпляре Mydate*/
Mydate.setMonth(4);
m=Mydate.getMonth(); // m=4
cout<<"\nd=" <<d << " m=" <<m << " y="<<y;
/*Изменить значение месяца на значение 5 в экземпляре BirthDate*/
BirthDate.setMonth(5);
m=BirthDate.getMonth(); // m=5
cout<<"\nd=" <<d << " m=" <<m << " y="<<y;
getch();
}
Рис.13 Работа конструктора класса
Заметим, что у класса может быть много конструкторов. Когда создается класс, то для инициализации его различных полей и создаются различные конструкторы. Хотя все они имеют одинаковое имя, совпадающее с именем класса, тем не менее компилятор их различает по наборам параметров и типов.
Конструктор копирования
Конструктор копирования — это специальный вид конструктора, получающий в качестве единственного параметра указатель на объект этого же класса.
Например:
К::К(const &К) { /* тело конструктора */ };
где К — имя класса.
Этот конструктор вызывается в тех случаях, когда новый объект создается путем копирования существующего:
-
при описании нового объекта с инициализацией другим объектом;
-
при передаче объекта в функцию по значению;
-
при возврате объекта из функции.
Если не указать ни одного конструктора копирования, то компилятор создаст его автоматически.
Следующий конструктор копирования выполняет поэлементное копирование всех полей:
class X {
int а, b; /* Вопрос для самопроверки: какими данными (приватными или публичными) являются эти переменные для класса X? */
Public:
X (int i, int j) {a = i; b = j;}