Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Языки программирования.docx
Скачиваний:
3
Добавлен:
09.09.2019
Размер:
64.85 Кб
Скачать

Массив объекта

Массив может хранить объекты любого типа, как встроенного, так и собственного пользовательского типа. При объявлении массива компилятору сообщают количество хранимых объектов (размер массива), что позволит выделить участок памяти требуемого размера и тип объекта. Для того, чтобы объекты могли быть созданы при определении массива, класс должен обладать конструктором по умолчанию без параметров. Для обращения к членам массива сначала используется операция индексации ([..]), а затем, с помощью операции прямого доступа, получают доступ к определенному члену класса. Количество выделенной памяти для всего массива, компьютер выделяет на основании типа.

Int main()

{

Box boxes[5];

Box cigar(8.0,5.0,1.0);

Boxes[3]=cigar;

Cout<<”the volume of boxes[1]= “<<boxes[1].Volume()<<endl;

Cout<<”the volume of boxes[4]= “<<boxes[4].Volume()<<” =”Volume of cigar= “<<cigar.Volume()<<endl;

Return 0;

}

Деструкторы

Деструктор – функция, которая уничтожает объект, когда необходимость в нем отпадает или когда он выходит из области видимости. Разрушение объектов включает освобождение памяти, занятой данными членами объекта, за исключением статических членов, которые продолжают существовать. Даже когда не остается ни одного экземпляра класса. Деструктор – особая функция, имя которой совпадает с именем класса, но предваренное символом ~(тильда). Деструктор не возвращает значения (не имеет типа возврата) и не принимает параметров, следовательно его невозможно перегружать и он может быть в классе только один.

Class Box

{public:

~Box(){cout<<”destructor called/n”;}

Box(double lv=1.0, double hv=1.0, double bv=1.0)

{L=lv;H=hv;W=bv;

Cout<<”constructor called\n”;}

Double Volume(){return L*H*W;}

Private:

Double L,H,W;

};

Int main()

{ Box boxes[5]

Box cigar(8.0,5.0,1.0);

Box match(2.2,1.1,0,5);

Box* PB1=&cigar;

Box* PB2=Null;

Cout<<endl<<”the cigar Volume= ”<<PB1->Volume()<<endl;

PB2=boxes;

Boxes[2]=match;

Cout<<”the volume of boxes[2]= “<<(PB+2)->Volume()<<endl;

Return0;

}

Замечание:

При присваивании указателю PB2 массива boxes, происходит передача адреса первого элемента массива boxes.

При вызове Volume(), для выбора необходимого нам 3-го элемента массива, мы можем просто прибавить к нашей позиции(1-й элемент) еще 2 позиции и получим 3-й элемент.

Деструкторы и динамическое распределение памяти

Условия задачи:

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

Воспользоваться кучей можно с помощью оператора new. Чтобы освободить занятый участок кучи, используется оператор delete. Все переменные, располагающиеся в куче, называются динамическими переменными/массивами. Такие динамические объекты не имеют имен, они создаются в процессе выполнения программы. К ним можно обратиться только через их адреса, то есть через указатели.

#include<cstring>

#include<iostream>

Double* pmass=new double [10];

Cout<<”enter the elements of the array: ”<<endl;

For (int i=0;i<10;i++)

Cin>>*(pmass+i); //(можно pmass[i])

Double** parray=new double*[n];

For (int i=0;i<n;i++)

Parray[i]=new double[n];

For (int i=0;i<n;i++)

For (int j=0;j<n;j++)

Cin>>*(*(parray+i)+j);

//cin>>parray[i][j];

Delete[] pmass;

Pmass=0; //теперь можно снова использовать данный указатель.

For int (int i=0;i<n;i++)

Delete parray[i];

Delete[] parray;

Теперь само задание:

Class Message

{private:

Char* pmessage;

Public:

Void ShowIt(){cout<<endl<<pmessage;}

Message(const char* text=”default message”)

{pmessage=new char(strlen(text)+1);

Strcpy(pmessage,text);}

~Message();

};

Messge::~Message()

{ cout<<”destructor called\n”;

Delete [] pmessage;}

Int main()

{ Message mess1 (“visual studio 2010”);

Message PM=new Message (“The programming technology C++”);

Mess1.ShowIt();

PM->ShowIt();

Cout<<endl;

Delete PM; // - иначе динамический объект не освободит занимаемую память

Return 0;

}

Так как объекты в конструкторе теперь создаются в области свободного хранилища, мы должны написать деструктор, для того, чтобы освободить память, выделенную для текстового сообщения. Если не создать деструктор класса, то не будет никакой возможности освободить память, выделенную объекту. Поэтому если представить этот класс без деструктора и, затем создать большое количество объектов типа message, то память кучи будет постепенно съедаться, пока программа не завершится аварийно. Подобное может произойти, например, если создать временный объект в функции, которая в программе вызывается многократно, и мы ожидаем, что объект уничтожится при возврате из функции, а на самом деле такое не произойдет без явного указания операции delete.

Замечание: на самом деле указатель при выходе из области видимости уничтожается, но память, на которую они указывали остается занятой. Ее, впоследствии, ни чем не занять. Поэтому в течении выполнении программы будет накапливаться все больше и больше занятой памяти, не имеющей адреса. Данное явление называется утечкой памяти.

При запуске вышеупомянутой программы в результате без строки delete, получаем 1 вызов деструктора, вместо двух. Такой вызов деструктора соответствует уничтожению объекта mess1, который является статическим объектом. Второй объект является динамическим и поэтому, компилятор, увидев операцию new, ожидает вызова операции delete для его уничтожения. Таким образом, для того, чтобы вызвать деструктор для динамических объектов, необходимо указать в явном виде операцию delete в той области видимости, где был создан динамический объект.