Классы в C++. ООП. Конструктор

В C++ для упрощения процесса инициализации объекта предусмотрена специальная функция, которая называется конструктором. Имя конструктора совпадает с именем класса, конструктор запускается автоматически при объявлении переменной типа class. Функции-конструкторы не возвращают значение, но при их описании не следует указывать в качестве возвращаемого значения тип void. Конструктор автоматически запускается на выполнение для каждого экземпляра класса при его описании. Чаще всего конструктор служит для инициализации полей экземпляра класса.

Добавим в наш класс complex (созданный на прошлом уроке) конструктор; программа с его использованием приведена ниже.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include «stdafx.h»
#include <iostream>
#include <math.h>
#define PI 3.14159
using namespace std;
//объявляем класс complex. Обратите внимание, что внутри класса указаны
//только прототипы методов, а сами функции описаны за пределами класса
class complex
{
//открытые методы
public:
//прототип конструктора класса
complex();
//прототип метода modul()
double modul();
//прототип метода argument()
double argument();
private:
double x;
double y;
//прототип метода show_complex
void show_complex();
};
//главная функция
int main()
{
setlocale(LC_ALL,«Rus»);
//описываем экземпляр класса, при выполнение программы после
//создания переменной автоматически вызывается конструктор
complex chislo;
cout<<«Модуль комплексного числа = «<<chislo.modul();
cout<<endl<<«Аргумент комплексного числа = «<<chislo.argument()<<endl;
system(«pause»);
return 1;
}
//текст функции конструктора класса complex
complex::complex()
{
cout<<«введите x \t«; cin>>x;
cout<<«введите y \t«; cin>>y;
//вызов закрытого метода show_complex из открытого метода vvod
show_complex();
}
//текст метода modul класса complex
double complex::modul()
{ return pow(x*x+y*y,0.5); }
//текст метода argument класса complex
double complex::argument()
{ return atan2(y,x)*180/PI; }
//текст метода show_complex класса complex
void complex::show_complex()
{
if (y>=0) cout<<x<<y<<«+»<<y<<«i»<<endl;
else cout<<x<<y<<«i»<<endl;
}

Если члены класса являются массивами (или указателями), то в конструкторе логично предусмотреть выделение памяти для них. Рассмотрим это на примере.

Задача

С использованием классов решить следующую задачу. Заданы координаты n точек k-мерном пространстве. Найти точки, расстояние между которыми наибольшее и наименьшее.

Текст программы приведен ниже.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include «stdafx.h»
#include <iostream>
#include <math.h>
#define PI 3.14159
using namespace std;
class prostr //описываем класс prostr
{
//открытые методы
public:
//конструктор класса
prostr();
double poisk_min();
double poisk_max();
int vivod_result();
int delete_a();
//все члены класса — закрытые
private:
int k; int jmin; int imax; int jmax; int imin; int n;
double **a; double min; double max;
};
//главная функция
void main()
{
setlocale(LC_ALL,«Rus»);
//описание переменной — экземпляра класса prostr
prostr x;
//вызов метода poisk_max для поиска максимального
//расстояния между точками в k-мерном пространстве
x.poisk_max();
//вызов метода poisk_max для поиска минимального
//расстояния между точками в k-мерном пространстве
x.poisk_min();
//вызов метода vivod_result для вывода результатов
x.vivod_result();
//вызов функции delete_a
x.delete_a();
system(«pause»);
}
//текст функции конструктора класса prostr
prostr::prostr()
{
int i, j;
cout<<«Введите размерность пространства «; cin>>k;
cout<<«Введите количество точек «; cin>>n;
a=new double*[k];
for(i=0; i<k; i++) a[i]=new double[n];
for(j=0; j<n; j++)
{
cout<<«Введите координаты «<<j<<» точки»<<endl;
for(i=0; i<k; i++)
cin>>a[i][j];
}
}
//текст метода poisk_max класса prostr
double prostr::poisk_max()
{
int i, j, l;
double s;
for (max=0, l=0; l<k; l++)
max+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
max=pow(max,0.5);
imax=0; jmax=1;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s>max)
{
max=s;
imax=i;
jmax=j;
}
}
return 0;
}
//текст метода poisk_min класса prostr
double prostr::poisk_min()
{
int i, j, l;
double s;
for (min=0, l=0; l<k; l++)
min+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
min=pow(min,0.5);
imin=0; jmin=1;
for(i=0; i<k; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s<min)
{
min=s;
imin=i;
jmin=j;
}
}
return 0;
}
//текст метода vivod_result класса prostr
int prostr::vivod_result()
{
int i, j;
for (i=0; i<k; cout<<endl, i++)
for (j=0; j<n; j++)
cout<<a[i][j]<<«\t«;
cout<<«max=»<<max<<«\t номера «<<imax<<» «<<jmax<<endl;
cout<<«min=»<<min<<«\t номера «<<imin<<» «<<jmin<<endl;
return 0;
}
//текст функции деструктор класса prostr
int prostr::delete_a()
{
delete []a;
return 0;
}

Так будет выглядеть результат работы программы:

Программа с классом prostr

Перегрузка функций-конструкторов

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include «stdafx.h»
#include <iostream>
#include <math.h>
#define PI 3.14159
using namespace std;
class prostr
{
public:
prostr(int, int);
prostr();
double poisk_min();
double poisk_max();
int vivod_result();
int delete_a();
private:
int n; int k; int jmin; int imax; int jmax; int imin;
double **a; double min; double max;
};
void main()
{
//можно вызывать конструктор с параметрами
setlocale(LC_ALL,«Rus»&##41;;
prostr x(3,5);
//или без prostr x; в этом случае будет вызываться тот же
//конструктор, что и в предыдущем примере
x.poisk_max();
x.poisk_min();
x.vivod_result();
x.delete_a();
system(«pause»);
}
prostr::prostr()
{
int i, j;
cout<<«Введите размерность пространства «;
cin>>k;
cout<<«Введите количество точек «;
cin>>n;
a=new double*[k];
for(i=0; i<k; i++)
a[i]=new double[n];
for(j=0; j<n; j++)
{
cout<<«Введите координаты «<<j<<» точки»<<endl;
for(i=0; i<k; i++)
cin>>a[i][j];
}
}
//текст второго конструктора.
//ОБРАТИТЕ ВНИМАНИЕ! Нельзя в качестве формальных параметров
//конструктора использовать переменные n и k, потому что это
//имена членов класса. Если в качестве формальных параметров
//указать n и k, то внутри конструктора будут использоваться
//локальные переменные n и k, но при этом
//члены класса prostr n и k будут неопределенны
prostr::prostr(int k1, int n1)
//входными параметрами являются размерность пространства n1
//и количество точек в пространстве k1
{
int i, j;
//присваиваем членам класса n и k значения входных
//параметров конструктора
k=k1;
n=n1;
a=new double*[k];
for (i=0; i<k; i++)
a[i]=new double [n];
for (j=0; j<n; j++)
{
cout<<«Введите координаты «<<j<<» точки»<<endl;
for(i=0; i<k; i++)
cin>>a[i][j];
}
}
double prostr::poisk_max()
{
int i, j, l;
double s;
for (max=0, l=0; l<k; l++)
max+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
max=pow(max,0.5);
imax=0; jmax=1;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s>max)
{
max=s;
imax=i;
jmax=j;
}
}
return 0;
}
double prostr::poisk_min()
{
int i, j, l;
double s;
for (min=0, l=0; l<k; l++)
min+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
min=pow(min,0.5);
imin=0; jmin=1;
for(i=0; i<k; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s<min)
{
min=s;
imin=i;
jmin=j;
}
}
return 0;
}
int prostr::vivod_result()
{
int i, j;
for (i=0; i<k; cout<<endl, i++)
for (j=0; j<n; j++)
cout<<a[i][j]<<«\t«;
cout<<«max=»<<max<<«\t номера»<<imax<<» «<<jmax<<endl;
cout<<«min=»<<min<<«\t номера»<<imin<<» «<<jmin<<endl;
return 0;
}
int prostr::delete_a()
{
delete []a;
return 0;
}

Параметры по умолчанию в конструкторе

Теперь рассмотрим, как можно использовать параметры по умолчанию в конструкторе. Оставим в нашей задаче только конструктор с параметрами (n1 и k1), но сделаем их по умолчанию равными 2 и 10 соответственно. В этом случае, при описании экземпляра класса без параметров n по умолчанию будет равно 2, а k — 10. Однако можно описать экземпляр класса, передав в него любые значения n и k. Например:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include «stdafx.h»
#include <iostream>
#include <math.h>
#define PI 3.14159
using namespace std;
class prostr
{
public:
//прототип конструктора с параметрами по умолчанию k=2, n=10
prostr(int k1=2, int n1=10);
double poisk_min();
double poisk_max();
int vivod_result();
int delete_a();
private:
int n; int k; int jmin; int imax; int jmax; int imin;
double **a; double min; double max;
};
void main()
{
setlocale(LC_ALL,«Rus»);
//экземпляр класса можно описать вот так
prostr x(2,3);
//или так — prostr x; в этом случае k=2 n=10
x.poisk_max();
x.poisk_min();
x.vivod_result();
x.delete_a();
system(«pause»);
}
//конструктор с параметрами по умолчанию k=2, n=10
prostr::prostr(int k1, int n1)
{
int i, j;
k=k1;
n=n1;
a=new double*[k];
for(i=0; i<k; i++)
a[i]=new double[n];
for(j=0; j<n; j++)
{
cout<<«Введите координаты «<<j<<» точки»<<endl;
for(i=0; i<k; i++)
cin>>a[i][j];
}
}
double prostr::poisk_max()
{
int i, j, l;
double s;
for (max=0, l=0; l<k; l++)
max+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
max=pow(max,0.5);
imax=0; jmax=1;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s>max)
{
max=s;
imax=i;
jmax=j;
}
}
return 0;
}
double prostr::poisk_min()
{
int i, j, l;
double s;
for (min=0, l=0; l<k; l++)
min+=(a[l][0]a[l][1])*(a[l][0]a[l][1]);
min=pow(min,0.5);
imin=0; jmin=1;
for(i=0; i<k; i++)
for(j=i+1; j<n; j++)
{
for (s=0, l=0; l<k; l++)
s+=(a[l][i]a[l][j])*(a[l][i]a[l][j]);
s=pow(s,0.5);
if (s<min)
{
min=s;
imin=i;
jmin=j;
}
}
return 0;
}
int prostr::vivod_result()
{
int i, j;
for (i=0; i<k; cout<<endl, i++)
for (j=0; j<n; j++)
cout<<a[i][j]<<«\t«;
cout<<«max=»<<max<<«\t номера»<<imax<<» «<<jmax<<endl;
cout<<«min=»<<min<<«\t номера»<<imin<<» «<<jmin<<endl;
return 0;
}
int prostr::delete_a()
{
delete []a;
return 0;
}

Конструктор копирования

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

public: name_constructor(type_class & name);

Здесь name_constructor — имя конструктора копирования, name — передаваемый в конструктор копирования экземпляр класса (type_class — имя класса).

Рейтинг
( Пока оценок нет )
Загрузка ...