Достаточно часто при работе с объектами используются члены-данные, которые представляют массивы с переменной длиной. В этом случае могут быть использованы два варианта выбора структуры объекта.
1-ый спосо б – определение класса, в котором определен член-данное- массив, для которого указан некоторый размер. Этот размер представляет максимальную величину, которую может иметь при обработке этот массив. Но для того, чтобы работать с объектами, которые имеют массивы с размерами, отличающимися от этого максимального размера, определяется член-данное целого типа, в котором фиксируется действительное количество элементов массива.
Пример
class q
{
int x[12]; // массив x с максимальной длиной ,равной 12
int n;.// действительное количество элементов
public:
q(int n1…..) {n=n1; ……}; /* конструктор, в котором передается действительное количество элементов массива x, которое используется при вводе и обработке; n1-параметр для передачи действительного количества элементов */
}; // конец определения класса
Недостатком этого метода является то, что при создании всех объектов этого класса для каждого объекта будет выделяться память для 12-ти элементов целого типа, а использоваться только часть этого массива; рабочий размер этого массива, например, определяется в конструкторе формальным параметром n1.
2-ой способ- определение класса, в котором определяется член-данное, представляющее указатель на массив элементов определенного типа. В этом случае при работе с объектами во время исполнения программы для каждого объекта выделяется память определенного размера (то есть используется динамическая память). При использовании этого способа также возможно использование двух вариантов.
Способ 2а
В этом случае при передаче в объект фактического массива в член-функции ввода данных записывается указатель на фактический массив и действительное количество элементов этого массива.
Пример
#include<iostream.h>
#include <conio.h>
class q1
{
int *x; // указатель на массив целых чисел
int n; // количество элементов в массиве
public:
q1(int *y,int n1)/* конструктор, передающий массив y и количество n1 обрабатываемых элементов */
{ x=y; //присвоение адреса внешнего массива
for(int i=0;i<n1;i++)
{
cout<<"x[i]="<<x[i]<<" y[i]="<<y[i]<<endl;/* распечатка передаваемого массива и массива объекта*/
}
n=n1; /* фиксация действительного размера массива */
} .// конец определения конструктора
}; // конец определения класса
int main() // главная функция
{ clrscr();
int f[4]={4,3,2,1};
q1 obj1(f,3); // задание в объекте адреса внешнего массива f
}// конец главной функции
Недостатком этого способа является то, что в этом случае данные объекта и данные внешней (главной) функции имеют одинаковые адреса (т. е. являются связанными по адресам); поэтому данные объекта фактически незащищены, хотя они имеют режим доступа private.
Способ 2б
В рассматриваемом способе используется динамическая память для массива.
Для того, чтобы избежать указанного в способе 2а недостатка, необходимо реализовать следующий алгоритм:
- дать запрос на выделение собственной памяти для передаваемого массива. Это реализуется с помощью оператора new , который позволяет динамически выделить память соответствующего размера.
- переписать в эту память передаваемый массив.
В этом случае программы обработки по членам-функциям и внешним функциям будут разделены по адресам данных.
Пример
В данном случае используется та же структура объекта, что и в примере способа 2а.
#include<iostream.h>
#include <conio.h>
class q1
{
int *x; //указатель на массив целых чисел
int n;// действительное количество элементов в массиве
public:
q1(int *y,int n1)// конструктор для передачи n1 элементов целого типа
{ x=new int [n1]; /* запрос памяти для массива из n1 элементов целого типа*/
for(int i=0;i<n1;i++)
{
x[i]=y[i];// передача i-го элемента
cout<<"x[i]="<<x[i]<<" y[i]="<<y[i]<<endl;
}
n=n1;
}
}; // конец определения класса
int main()
{ clrscr();
int f[4]={4,3,2,1};
q1 obj1(f,3); /* в этом случае при исполнении конструктора выделяется память для трех элементов целого типа, в которую копируются три элемента внешнего массива f */
}
Примечание
Замечание о необходимости использования динамической памяти, конечно, справедливы и для случая использования простых скалярных величин. Но особенно это актуально, как было уже сказано, для массивов.
Дата: 2019-03-05, просмотров: 253.