Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.95/43: Рейтинг темы: голосов - 43, средняя оценка - 4.95
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110

Класс вектор. Комментарии к коду.

03.06.2011, 15:39. Показов 9029. Ответов 33

Студворк — интернет-сервис помощи студентам
Многое я в этом коде не понимаю, поэтому напишу , что понятно мне. Исправьте меня если я не прав. Спасибо
Delphi
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
unit Unit2;
interface
uses
  SysUtils;
type
  TVector = class          // имя класса
    private
      FItems: array of Double; // поля класса-динамический массив
      function GetItem(Index: Integer): Double; // метод класса- с парматром
 
 
    public
      constructor Create(AItems: array of Double); //  конструктор 
      destructor Destroy; override;  //Зачем у деструктора  override; ?
      property Items[Index: Integer]: Double read GetItem; default; // В обычных свойствах  функция для чтения без параметра, но здесь массив свойств . Поэтому она с параметром. А вот зачем default ?
  end;
implementation
{ TVector }
constructor TVector.Create(AItems: array of Double); // Реализация конструктора
var
  i: Integer;
begin
  SetLength(FItems, Length(AItems)); // создание динамического массива FItems длинной AItems
  for i := Low(AItems) to High(AItems) do  // цикл от наименьшего индекса динамического массива до наибольшего
    FItems[i] := AItems[i]; //  Эту строчку я вообще не понимаю
end;
destructor TVector.Destroy; // реализация деструктора
begin
  SetLength(FItems, 0); //  Уничтожение динамического массива
  inherited; // унаследованый деструктор
end;
function TVector.GetItem(Index: Integer): Double; // Реализация метода GetItem
begin
  if Index in [Low(FItems)..High(FItems)] then  // если Index  лежит в интервале  от наименьшего до наибольшого индекса массива 
    Result := FItems[Index] // То что ? Строка тоже не понятна
  else  иначе
    raise Exception.Create('Index is not Valid!'); //  Вообще не понятно
end;
end.
 Комментарий модератора 
Теги кода изменены модератором. Для оформления кода Delphi следует выделить этот код и на панели редактирования сообщения нажать кнопку "DELPHI".
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.06.2011, 15:39
Ответы с готовыми решениями:

Комментарии к коду
код в текстовом документе

Комментарии к коду
Помогите написать комментарии к коду. Шифрование DES unit DES; interface Uses Windows, Classes, SysUtils, Math, Dialogs; ...

Комментарии к коду
Здравствуйте. Можете пожалуйста добавить комментарии к данному коду? Что значит Sender as TShape и т.д.? Заранее спасибо. procedure...

33
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
09.06.2011, 13:18  [ТС]
Студворк — интернет-сервис помощи студентам
Скобки поставил : Incompatible types: Array and TVector (
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
09.06.2011, 15:54
Да, в самом деле - в GetScalarMulty() в качестве параметра надо массив координат вектора передавать. Либо можно переделать метод так, чтобы в качестве параметра передавать ему второй экземпляр TVector, из которого будут взяты координаты.
---
Наверное, лучше так поступим - я вечером напишу реализацию и выложу здесь.
1
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
09.06.2011, 15:58  [ТС]
Спасибо, жду )
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
09.06.2011, 20:53
Готово.
Модуль, где объявлен класс TVector:
Delphi
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
136
137
138
139
140
unit UVector;
 
interface
 
type
  TArrItems = array of Extended;
 
  TVector = class(TObject)
  private
    FItems : TArrItems;
  protected
    function GetItem(aIndex : Integer) : Extended; virtual;
    procedure SetItem(aIndex : Integer; const aValue : Extended); virtual;
    function GetArrItems : TArrItems; virtual;
    procedure SetArrItems(const aArrItems : TArrItems); virtual;
    function GetItemsCount : Integer;
    procedure SetItemsCount(const aCount : Integer);
    property ArrItems : TArrItems read GetArrItems write SetArrItems;
  public
    constructor Create; overload;
    constructor Create(const aCount : Integer); overload;
    constructor Create(const aArrItems : TArrItems); overload;
    destructor Destroy; override;
    property Items[aIndex : Integer] : Extended read GetItem write SetItem; default;
    property ItemsCount : Integer read GetItemsCount write SetItemsCount;
 
    function ScalarMultiply(const aVector : TVector) : Extended; virtual;
    function ToString : String; virtual;
  end;
 
implementation
 
uses SysUtils;
 
{ TVector }
 
constructor TVector.Create;
begin
  inherited;
  FItems := nil;
end;
 
constructor TVector.Create(const aCount: Integer);
begin
  inherited Create;
  ItemsCount := aCount;
end;
 
constructor TVector.Create(const aArrItems : TArrItems);
begin
  inherited Create;
  FItems := aArrItems;
end;
 
destructor TVector.Destroy;
begin
  Finalize(FItems);
  inherited;
end;
 
function TVector.GetArrItems: TArrItems;
begin
  Result := FItems;
end;
 
function TVector.GetItem(aIndex: Integer): Extended;
const
  SelfName = 'TVector.GetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise ERangeError.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  Result := FItems[aIndex];
end;
 
function TVector.GetItemsCount: Integer;
begin
  Result := Length(FItems);
end;
 
procedure TVector.SetArrItems(const aArrItems: TArrItems);
begin
  FItems := aArrItems;
end;
 
procedure TVector.SetItem(aIndex: Integer; const aValue: Extended);
const
  SelfName = 'TVector.SetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise ERangeError.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  FItems[aIndex] := aValue;
end;
 
procedure TVector.SetItemsCount(const aCount: Integer);
const
  SelfName = 'TVector.SetItemsCount()';
begin
  if aCount < 0 then
    raise Exception.Create(SelfName + '. Ошибка! Вектор не может иметь отрицательную размерность.')
  ;
  SetLength(FItems, aCount);
end;
 
function TVector.ToString: String;
var
  i, h : Integer;
begin
  Result := '';
  h := High(FItems);
  for i := 0 to h do begin
    if Result <> '' then Result := Result + '; ';
    Result := Result + FloatToStr(FItems[i]);
  end;
  Result := '(' + Result + ')';
end;
 
function TVector.ScalarMultiply(const aVector: TVector): Extended;
const
  SelfName = 'TVector.ScalarMultiply()';
var
  i, h : Integer;
  ArrItems : TArrItems;
begin
  if (aVector = nil) then
    raise Exception.Create(SelfName + '. Ошибка! aVector = nil.')
  ;
  if ItemsCount <> aVector.ItemsCount then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  ArrItems := aVector.ArrItems;
  h := High(ArrItems);
  Result := 0;
  for i := 0 to h do
    Result := Result + FItems[i] * ArrItems[i]
  ;
end;
 
end.
Модуль формы:
Delphi
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
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
uses
  UVector;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  M = 4;
var
  V1, V2 : TVector;
  i : Integer;
  ScalarMulti : Extended;
begin
  Memo1.Clear;
 
  V1 := TVector.Create(M);
  V2 := TVector.Create(M);
  for i := 0 to V1.ItemsCount - 1 do begin
    V1.Items[i] := i;
    V2.Items[i] := (M - 1) - i;
  end;
 
  Memo1.Lines.Add('Вектора:');
  Memo1.Lines.Add('V1 = ' + V1.ToString);
  Memo1.Lines.Add('V2 = ' + V2.ToString);
  Memo1.Lines.Add('');
 
  ScalarMulti := V1.ScalarMultiply(V2);
  Memo1.Lines.Add('Скалярное произведение векторов равно: ' + FloatToStr(ScalarMulti));
 
  FreeAndNil(V1);
  FreeAndNil(V2);
end;
 
end.
Здесь можно код:
Delphi
1
2
3
4
  for i := 0 to V1.ItemsCount - 1 do begin
    V1.Items[i] := i;
    V2.Items[i] := (M - 1) - i;
  end;
переписать так:
Delphi
1
2
3
4
  for i := 0 to V1.ItemsCount - 1 do begin
    V1[i] := i;
    V2[i] := (M - 1) - i;
  end;
т. к., свойство Items объявлено со словом default.
Миниатюры
Класс вектор. Комментарии к коду.  
Вложения
Тип файла: rar TVector.rar (167.5 Кб, 65 просмотров)
0
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
09.06.2011, 21:17  [ТС]
Огромное спасибо ! Но нельзя ли с комментариями ? И в порядке бреда .Просто у меня задание звучит так: Написать класс вектор через массив свойств . То есть по-другому никак ?
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
09.06.2011, 21:21
Массив свойств - это и есть свойство Items в классе - то, которое с механизмом доступа по индексу.
---
Комменты напишу чуть позже - мне до дома ещё надо добраться.
0
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
09.06.2011, 21:30  [ТС]
Посмотрите, пожалуйста , что мой одногруппник написал ( у него такое же задание) . У кого из нас ответ отвечает заданию: Написать класс вектор через массив свойств.

Delphi
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
program Property_Array;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
{Пределы индексирования векторов}
const LOW = 0;
const LIMIT = 9;
 
{Определение типа элементов вектора}
Type VectorElements = array [LOW..LIMIT] of real;
 
{Определения класса "Вектор"}
type
  TVectorClass = class
  private
    {Место хранения элементов первого вектора}
    Mass1: VectorElements;
    {Место хранения элементов второго вектора}
    Mass2: VectorElements;
    {Место хранения элементов вектора-рузультата}
    ResultMass: VectorElements;
 
  protected
    {Объявление функции чтения элемента массива Mass1}
    function GetValue1(Index: integer): real;
    {Объявление процедуры записи элемента в массив Mass1}
    procedure SetValue1(Index: integer; Value: real);
    {Объявление функции чтения элемента массива Mass2}
    function GetValue2(Index: integer): real;
    {Объявление процедуры записи элемента в массив Mass2}
    procedure SetValue2(Index: integer; Value: real);
    {Объявление функции чтения элемента массива Result}
    function GetValue3(Index: integer): real;
    {Объявление процедуры записи элемента в массив Result}
    procedure SetValue3(Index: integer; Value: real);
 
  public
 
    {Длинна вектора результата}
    VectorLong: integer;
 
    {Результат умножения двух векторов}
    Multitude: real;
 
    {Процедура чтения вектора класса}
    procedure VectorRead(EnteringVector: string; var VectorMass: VectorElements;
    var VectorSize: integer);
 
    {Объявление конструктор создания объекта класса TVectorClass}
    constructor Create(EnteringVector1, EnteringVector2: string);
 
    {Объявление деструктора создания объекта класса TVectorClass}
    destructor Destroy;
 
    {Объявление свойства типа массив первого вектора класса TVectorClass}
    property Vector1[Index: integer]: real read GetValue1 write SetValue1;
 
    {Объявление свойства типа массив второго вектора класса TVectorClass}
    property Vector2[Index: integer]: real read GetValue2 write SetValue2;
 
    {Объявление свойства типа массив вектора-результата класса TVectorClass}
    property ResultVector[Index: integer]: real read GetValue3 write SetValue3;
 
    {Основные арифметические функции над векторами}
 
    {Объявление функции сложения двух векторов}
    procedure Add;
    {Объявление функции вычитания второго вектора из первого}
    procedure Subtraction;
    {Объявление функции скалярного умножения двух векторов}
    procedure ScaliarMultitude;
 
  end;
 
{Процедура чтения элемента из свойства-массива первого вектора}
function TVectorClass.GetValue1(Index: integer): real;
begin
  Result := Mass1[Index]
end;
 
{Процедура записи в элемен свойства-массива первого вектора}
procedure TVectorClass.SetValue1(Index: integer; Value: real);
begin
  Mass1[Index] := Value
end;
 
{Процедура чтения элемента из свойства-массива второго вектора}
function TVectorClass.GetValue2(Index: integer): real;
begin
  Result := Mass2[Index]
end;
 
{Процедура записи в элемен свойства-массива второго вектора}
procedure TVectorClass.SetValue2(Index: integer; Value: real);
begin
  Mass2[Index] := Value
end;
 
{Процедура чтения элемента из свойства-массива вектора-результата}
function TVectorClass.GetValue3(Index: integer): real;
begin
  Result := ResultMass[Index]
end;
 
{Процедура записи в элемен свойства-массива вектора-результата}
procedure TVectorClass.SetValue3(Index: integer; Value: real);
begin
  ResultMass[Index] := Value
end;
 
procedure TVectorClass.VectorRead(EnteringVector: string; var VectorMass:
VectorElements; var VectorSize: integer);
var
  {Флаг ввода числовых данных из буффера ввода}
  Entering: boolean;
 
  {Счётчик эллементов буфера ввода}
  Caunter1: integer;
 
  {Буфер итогового элемента вектора}
  Number: string;
 
begin
 
  {Наследование всех функций конструктора Create класса TObject}
  inherited Create;
 
  if EnteringVector <> '' then
  begin
    {Инициализация переменной размера вектора}
    VectorSize := LOW - 1;
    {Инициализация буфера итогового элемента вектора}
    Number := '';
    {Инициализация флага считывания значащих цифр и знаков}
    Entering := FALSE;
 
    {Цикл считывания данных из буффера ввода в вектор класса TVectorClass}
    for Caunter1 := 1 to Length(EnteringVector) do
    begin
      {Добавление знака к следующему элементу вектора}
      if (EnteringVector[Caunter1] = '-') or (EnteringVector[Caunter1] = '+')
      and (Entering = FALSE) then
      begin
        Number := EnteringVector[Caunter1]
      end;
 
      {Проверка на наличие значащей части элемента вектора}
      if (EnteringVector[Caunter1] >= '0') and (EnteringVector[Caunter1] <= '9')
      or ((EnteringVector[Caunter1] = '.') and (Entering = TRUE)) then
      begin
        {Накопление в буфере элемента значащих цифр и знаков}
        Number := Number + EnteringVector[Caunter1];
        {Начало считывания значащих знаков и цифр из буффера ввода}
        Entering := TRUE
      end
      else
      begin
        {Конец значащей последовательности цифр и знаков ввода}
        if Entering = TRUE then
        begin
          {Увеличение размера вектора на единицу}
          VectorSize := VectorSize + 1;
          {Сохранение полученной значащей части в эллемент вектора в массив Mass}
          VectorMass[VectorSize] := StrToFloat(Number);
 
          {Обнуление буфера итогового элемента массива}
          Number := '';
          {Флаг указывает на конец считывания значащих цифр и знаков}
          Entering := FALSE;
        end
      end
    end;
    {Последним символом была значащая цифра или знак ввода}
    if Entering = TRUE then
    begin
      {Увеличение размера вектора на единицу}
      VectorSize := VectorSize + 1;
 
      {Проверка на последние ненужные символы}
      if (Number <> '-') and (Number <> '+') then
      begin
        {Сохранение полученной значащей части в эллемент вектора в массив Mass}
        VectorMass[VectorSize] := StrToFloat(Number)
      end
    end
  end
end;
 
{Описание деструктора объекта (вектора) класса TVectorClass}
destructor TVectorClass.Destroy;
begin
  {Наследование всех функций деструктора Destroy класса TObject}
  inherited Destroy;
end;
 
{Описание конструктора вектора класса TVectorClass вместе с его инициализацией}
constructor TVectorClass.Create(EnteringVector1, EnteringVector2: string);
var
  {Переменные размеров первого и второго векторов}
  Limit1 {Первый вектор}, Limit2 {Второй вектор}: integer;
 
begin
  {Наследование всех функций конструктора Create класса TObject}
  inherited Create;
 
  {Инициализация векторов-аргументов}
  VectorRead(EnteringVector1, Mass1, Limit1);
  VectorRead(EnteringVector2, Mass2, Limit2);
 
  {Выбор оптимального размера вектора-рузультата арифметических дейсвтий,
  изходя из размеров векторов-аргументов}
  if Limit1 >= Limit2 then
  begin
    VectorLong := Limit1
  end
  else
  begin
    VectorLong := Limit2
  end
end;
 
 
{Описание функции сложения двух векторов}
procedure TVectorClass.Add;
var
  {Счётчик цикла попарного сложения элементов двух векторов}
  Caunter1: integer;
begin
  {Цикл попарного сложения элементов двух векторов}
  for Caunter1 := LOW to VectorLong do
  begin
    ResultMass[Caunter1] := Mass1[Caunter1] + Mass2[Caunter1]
  end
end;
 
{Описание функции вычитания второго вектора из первого}
procedure TVectorClass.Subtraction;
var
  {Счётчик цикла попарного вычитания элементов вторго вектора из первого}
  Caunter1: integer;
begin
  {Цикл попарного вычитания элементов второго вектора из первого}
  for Caunter1 := LOW to VectorLong do
  begin
    ResultMass[Caunter1] := Mass1[Caunter1] - Mass2[Caunter1]
  end
end;
 
{Описание функции скалярного умножения двух векторов}
procedure TVectorClass.ScaliarMultitude;
var
  {Счётчик цикла скалярного умножения двух векторов}
  Caunter1: integer;
begin
  {Инициализа результата функции}
  Multitude := 0;
  {Цикл скалярного умножения двух векторов}
  for Caunter1 := LOW to VectorLong do
  begin
    Multitude := Multitude + (Mass1[Caunter1] * Mass2[Caunter1])
  end
end;
 
 
 
var
  {Объявление объектов класса TVectorClass}
  VectorsMath: TVectorClass;
 
  {Создание буфферов ввода эллементов первого и второго массива}
  ParametrsString1, ParametrsString2: string;
 
  {Переменная результата скалярного умножения векторов}
  MultitudeResult: real;
 
  {Счётчик цикла вывод на экран результирующего вектора}
  Caunter1: integer;
 
  {Объявление буферной переменной для считывания команд пользователя}
  Value, ExitValue: char;
 
begin
  { TODO -oUser -cConsole Main : Insert code here }
 
  {Принудительно введения разделителя целой и дробной части в действительных
  числах}
  DecimalSeparator := '.';
 
  {Циклическое выполнение арифметических операций над двумя векторами}
  repeat
    {Приглашение к вводу элементов первого вектора}
    write('Pleas enter first vector: ');
    {Чтение строки ввода с элементами первого вектора}
    readln(ParametrsString1);
 
    {Пустая строка}
    writeln;
 
    {Приглашение к вводу элементов второго вектора}
    write('Pleas enter seckond vector: ');
    {Чтение строки ввода с элементами второго вектора}
    readln(ParametrsString2);
 
    {Создание объекта типа TVectorClass}
    VectorsMath := TVectorClass.Create(ParametrsString1, ParametrsString2);
 
    {Обнулени буфера ввода элементов первого вектора}
    ParametrsString1 := '';
 
    {Обнулени буфера ввода элементов второго вектора}
    ParametrsString2 := '';
 
    {Пустая строка}
    writeln;
 
    {Функции выполнения простых арифметических дейстий над векторами}
 
    {Функция выполнения сложения двух векторорв}
    VectorsMath.Add;
    {Вывод результатов сложения двух векторов на экран}
    write('result of adding First Vector + Seckond Vector : [');
    for Caunter1 := LOW to VectorsMath.VectorLong - 1 do
    begin
      write(VectorsMath.ResultVector[Caunter1]:3:3, ' ,')
    end;
    writeln(VectorsMath.ResultVector[VectorsMath.VectorLong]:3:3, ']');
 
    {Пустая строка}
    writeln;
 
    {Функция выполнения вычитания второго вектора из первого}
    VectorsMath.Subtraction;
    {Вывод результатов вычитания двух векторов на экран}
    write('result of subtraction (First Vector - Seckond Vector): [');
    for Caunter1 := LOW to VectorsMath.VectorLong - 1 do
    begin
      write(VectorsMath.ResultVector[Caunter1]:3:3, ' ,')
    end;
    writeln(VectorsMath.ResultVector[VectorsMath.VectorLong]:3:3, ']');
    {Пустая строка}
    writeln;
 
    {Функция скалярного умножения двух векторорв}
    VectorsMath.ScaliarMultitude;
    {Вывод результата скалярного умножения двух векторов на экран}
    writeln('result vector of vector''s sclaliar multitude: ',
    VectorsMath.Multitude:3:3);
 
    {Вопрос на продолжение аналогичных действий}
    writeln;
    writeln('Repeate or End: Y/N');
    writeln;
    {Чтение ответа пользователя}
    readLn(Value);
    writeln;
    {Инициализация признака выход из цикла}
    ExitValue := 'N';
    {Подтверждение отрицательного ответа ответа}
    if (Value = 'N') or (Value = 'n') then
    begin
      writeln('Are you shuer?: Y/N');
      writeln;
      readln(ExitValue)
    end;
    writeln
 
  until (ExitValue = 'Y') or (ExitValue = 'y');
 
  {Уничтожение объекта класса TVectorClass}
  VectorsMath.Destroy;
 
end.
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
10.06.2011, 22:41
Вот следующая версия. В проекте реализован класс TVector - вектор и класс TVectors - коллекция векторов.
Код модуля с определениями классов.
Delphi
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
unit UVector;
 
interface
 
type
  TArrNums = array of Extended;
 
  //Класс: вектор.
  TVector = class(TObject)
  private
    FItems : TArrNums;
  protected
    function GetItem(aIndex : Integer) : Extended; virtual;
    procedure SetItem(aIndex : Integer; const aValue : Extended); virtual;
    function GetArrItems : TArrNums; virtual;
    procedure SetArrItems(const aArrItems : TArrNums); virtual;
    function GetCount : Integer; virtual;
    procedure SetCount(const aCount : Integer); virtual;
    function ToString : String; virtual;
 
    property ArrItems : TArrNums read GetArrItems write SetArrItems;
  public
    constructor Create; overload;
    constructor Create(const aCount : Integer); overload;
    constructor Create(const aArrItems : TArrNums); overload;
    constructor Create(const aArrItems : array of Extended); overload;
    destructor Destroy; override;
 
    property Items[aIndex : Integer] : Extended read GetItem write SetItem; default;
    property Count : Integer read GetCount write SetCount;
    property AsString : String read ToString;
 
    function ScalarMultiply(const aVector : TVector) : Extended; virtual;
    function Plus(const aVector : TVector) : TVector; virtual;
    function Minus(const aVector : TVector) : TVector; virtual;
  end;
 
  TArrVectors = array of TVector;
 
  //Класс: коллекция векторов.
  TVectors = class(TObject)
  private
    FItems : TArrVectors;
  protected
    function GetItem(aIndex : Integer) : TVector; virtual;
    procedure SetItem(aIndex : Integer; const aVector : TVector); virtual;
    function GetArrItems : TArrVectors; virtual;
    procedure SetArrItems(const aArrItems : TArrVectors); virtual;
    function GetCount : Integer; virtual;
 
    property ArrItems : TArrVectors read GetArrItems write SetArrItems;
  public
    constructor Create; overload;
    destructor Destroy; override;
 
    property Items[aIndex : Integer] : TVector read GetItem write SetItem; default;
    property Count : Integer read GetCount;
 
    procedure Insert(aValue : TVector; const aIndex : Integer); virtual;
    function Add(aValue : TVector) : Integer; virtual;
    function Remove(const aIndex : Integer) : TVector; virtual;
  end;
 
implementation
 
uses SysUtils;
 
{ TVector }
 
constructor TVector.Create;
begin
  inherited;
  FItems := nil;
end;
 
constructor TVector.Create(const aCount: Integer);
const
  selfName = 'TVector.Create()';
begin
  if aCount < 0 then
    raise Exception.Create(SelfName + '. Ошибка! Вектор не может иметь отрицательную размерность.')
  ;
  inherited Create;
  SetLength(FItems, aCount);
end;
 
constructor TVector.Create(const aArrItems : TArrNums);
begin
  inherited Create;
  FItems := aArrItems;
end;
 
constructor TVector.Create(const aArrItems: array of Extended);
var
  i, Len : Integer;
begin
  Len := Length(aArrItems);
  SetLength(FItems, Len);
  for i := 0 to Len - 1 do FItems[i] := aArrItems[i];
end;
 
destructor TVector.Destroy;
begin
  Finalize(FItems);
  inherited;
end;
 
function TVector.GetArrItems: TArrNums;
begin
  Result := FItems;
end;
 
function TVector.GetItem(aIndex: Integer): Extended;
const
  SelfName = 'TVector.GetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise Exception.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  Result := FItems[aIndex];
end;
 
function TVector.GetCount: Integer;
begin
  Result := Length(FItems);
end;
 
procedure TVector.SetArrItems(const aArrItems: TArrNums);
begin
  FItems := aArrItems;
end;
 
procedure TVector.SetItem(aIndex: Integer; const aValue: Extended);
const
  SelfName = 'TVector.SetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise Exception.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  FItems[aIndex] := aValue;
end;
 
procedure TVector.SetCount(const aCount: Integer);
const
  SelfName = 'TVector.SetCount()';
begin
  if aCount < 0 then
    raise Exception.Create(SelfName + '. Ошибка! Вектор не может иметь отрицательную размерность.')
  ;
  SetLength(FItems, aCount);
end;
 
function TVector.ToString: String;
var
  i, Len : Integer;
begin
  Result := '';
  Len := Count;
  for i := 0 to Len - 1 do begin
    if Result <> '' then Result := Result + '; ';
    Result := Result + FloatToStr(Items[i]);
  end;
  Result := '(' + Result + ')';
end;
 
function TVector.ScalarMultiply(const aVector: TVector): Extended;
const
  SelfName = 'TVector.ScalarMultiply()';
var
  i, Len : Integer;
begin
  if (aVector = nil) then
    raise Exception.Create(SelfName + '. Ошибка! aVector = nil.')
  ;
  if Count <> aVector.Count then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  Len := Count;
  Result := 0;
  for i := 0 to Len - 1 do
    Result := Result + Items[i] * aVector.Items[i]
  ;
end;
 
function TVector.Minus(const aVector: TVector): TVector;
const
  SelfName = 'TVector.Minus()';
var
  i, Len : Integer;
begin
  if (aVector = nil) then
    raise Exception.Create(SelfName + '. Ошибка! aVector = nil.')
  ;
  if Count <> aVector.Count then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  Len := Count;
  Result := TVector.Create(Len);
  for i := 0 to Len - 1 do
    Result.Items[i] := Items[i] - aVector.Items[i]
  ;
end;
 
function TVector.Plus(const aVector: TVector): TVector;
const
  SelfName = 'TVector.Plus()';
var
  i, Len : Integer;
begin
  if (aVector = nil) then
    raise Exception.Create(SelfName + '. Ошибка! aVector = nil.')
  ;
  if Count <> aVector.Count then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  Len := Count;
  Result := TVector.Create(Len);
  for i := 0 to Len - 1 do
    Result.Items[i] := Items[i] + aVector.Items[i]
  ;
end;
 
{ TVectors }
 
constructor TVectors.Create;
begin
  inherited;
  FItems := nil;
end;
 
destructor TVectors.Destroy;
begin
  Finalize(FItems);
  inherited;
end;
 
function TVectors.GetArrItems: TArrVectors;
begin
  Result := FItems;
end;
 
procedure TVectors.SetArrItems(const aArrItems: TArrVectors);
begin
  FItems := aArrItems;
end;
 
function TVectors.GetItem(aIndex: Integer): TVector;
const
  SelfName = 'TVectors.GetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise Exception.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  Result := FItems[aIndex];
end;
 
procedure TVectors.SetItem(aIndex: Integer; const aVector: TVector);
const
  SelfName = 'TVectors.SetItem()';
begin
  if ( aIndex < 0 ) and ( aIndex > High(FItems) ) then
    raise Exception.Create(SelfName + '. Ошибка! Недопустимый индекс.')
  ;
  FItems[aIndex] := aVector;
end;
 
function TVectors.GetCount: Integer;
begin
  Result := Length(FItems);
end;
 
procedure TVectors.Insert(aValue: TVector; const aIndex: Integer);
const
  SelfName = 'TVectors.Remove()';
var
  i, Len : Integer;
begin
  Len := Length(FItems);
  if (aIndex < 0) or (aIndex > Len ) then
    raise Exception.Create(SelfName + '. Ошибка! Неверный индекс.')
  ;
  SetLength(FItems, Len + 1);
  if aIndex < Len then begin
    for i := Len downto aIndex + 1 do FItems[i] := FItems[i - 1];
  end;
  FItems[aIndex] := aValue;
end;
 
function TVectors.Add(aValue: TVector): Integer;
begin
  Result := Length(FItems);
  Insert(aValue, Result);
end;
 
function TVectors.Remove(const aIndex : Integer): TVector;
const
  SelfName = 'TVectors.Remove()';
var
  i, Len : Integer;
begin
  Len := Length(FItems);
  if (aIndex < 0) or (aIndex >= Len ) then
    raise Exception.Create(SelfName + '. Ошибка! Неверный индекс.')
  ;
  Result := FItems[aIndex];
  for i := aIndex + 1 to Len - 1 do FItems[i - 1] := FItems[i];
  SetLength(FItems, Len - 1);
end;
 
end.
Код модуля формы:
Delphi
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
uses
  UVector;
 
//Работа с классом TVector.
procedure TForm1.Button1Click(Sender: TObject);
const
  M = 4;
var
  V1, V2, V3, V4, VRes : TVector;
  ArrItems : TArrNums;
  i : Integer;
  ScalarMulti : Extended;
begin
  Memo1.Clear;
  Memo1.Lines.Add('Работа с классом: TVector.');
  Memo1.Lines.Add('');
 
  VRes := nil;
 
  V1 := TVector.Create;
  V1.Count := M;
  for i := 0 to V1.Count - 1 do V1[i] := i;
 
  V2 := TVector.Create(M);
  for i := 0 to V2.Count - 1 do V2[i] := i + 1;
 
  SetLength(ArrItems, M);
  for i := 0 to M - 1 do ArrItems[i] := i + 2;
  V3 := TVector.Create(ArrItems);
  ArrItems := nil;
 
  V4 := TVector.Create([3, 4, 5, 6]);
 
  Memo1.Lines.Add('Созданы вектора:');
  Memo1.Lines.Add('V1 = ' + V1.AsString);
  Memo1.Lines.Add('V2 = ' + V2.AsString);
  Memo1.Lines.Add('V3 = ' + V3.AsString);
  Memo1.Lines.Add('V4 = ' + V4.AsString);
  Memo1.Lines.Add('');
 
  ScalarMulti := V1.ScalarMultiply(V2);
  Memo1.Lines.Add('Скалярное произведение векторов V1 и V2 равно: ' + FloatToStr(ScalarMulti));
  Memo1.Lines.Add('');
 
  FreeAndNil(VRes);
  VRes := V4.Minus(V3);
  Memo1.Lines.Add('Вектор, равный разности векторов V4 и V3: ' + VRes.AsString);
  Memo1.Lines.Add('');
 
  FreeAndNil(VRes);
  VRes := V1.Plus(V2);
  Memo1.Lines.Add('Вектор, равный сумме векторов V1 и V2: ' + VRes.AsString);
  Memo1.Lines.Add('');
 
  FreeAndNil(V1);
  FreeAndNil(V2);
  FreeAndNil(V3);
  FreeAndNil(V4);
  FreeAndNil(VRes);
 
  Memo1.Lines.Add('Вектора удалены из памяти.');
end;
 
//Работа с классами: TVector и TVectors.
procedure TForm1.Button2Click(Sender: TObject);
const
  M = 4;
var
  Vecs : TVectors;
  ArrItems : TArrNums;
  i, Index : Integer;
  ScalarMulti : Extended;
begin
  Memo1.Clear;
  Memo1.Lines.Add('Работа с классами: TVector и TVectors.');
  Memo1.Lines.Add('');
 
  Vecs := TVectors.Create;
 
  Index := Vecs.Add( TVector.Create );
  Vecs[Index].Count := M;
  for i := 0 to Vecs[Index].Count - 1 do Vecs[Index][i] := i;
 
  Index := Vecs.Add( TVector.Create(M) );
  for i := 0 to Vecs[Index].Count - 1 do Vecs[Index][i] := i + 1;
 
  SetLength(ArrItems, M);
  for i := 0 to M - 1 do ArrItems[i] := i + 2;
  Vecs.Add( TVector.Create(ArrItems) );
  ArrItems := nil;
 
  Vecs.Add( TVector.Create([3, 4, 5, 6]) );
 
  Memo1.Lines.Add('Перечень векторов в коллекции:');
  for i := 0 to Vecs.Count - 1 do begin
    Memo1.Lines.Add('V' + IntToStr(i) + ' = ' + Vecs[i].AsString);
  end;
  Memo1.Lines.Add('');
 
  ScalarMulti := Vecs[0].ScalarMultiply(Vecs[1]);
  Memo1.Lines.Add('Скалярное произведение векторов V0 и V1 равно: ' + FloatToStr(ScalarMulti));
  Memo1.Lines.Add('');
 
  Index := Vecs.Add( Vecs[3].Minus(Vecs[2]) );
  Memo1.Lines.Add('Вектор, равный разности векторов V3 и V2: ' + Vecs[Index].AsString);
  Memo1.Lines.Add('');
 
  Index := Vecs.Add( Vecs[0].Plus(Vecs[1]) );
  Memo1.Lines.Add('Вектор, равный сумме векторов V0 и V1: ' + Vecs[Index].AsString);
  Memo1.Lines.Add('');
 
  Memo1.Lines.Add('Перечень векторов в коллекции:');
  for i := 0 to Vecs.Count - 1 do begin
    Memo1.Lines.Add('V' + IntToStr(i) + ' = ' + Vecs[i].AsString);
  end;
  Memo1.Lines.Add('');
 
  for i := 0 to Vecs.Count - 1 do Vecs[i].Free;
  Memo1.Lines.Add('Вектора удалены из памяти.');
  Vecs.Free;
  Memo1.Lines.Add('Коллекция удалена из памяти.');
end;
 
end.
Миниатюры
Класс вектор. Комментарии к коду.   Класс вектор. Комментарии к коду.  
Вложения
Тип файла: rar TVector и TVectors.rar (170.4 Кб, 56 просмотров)
2
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
11.06.2011, 00:16
Цитата Сообщение от Beren Посмотреть сообщение
У кого из нас ответ отвечает заданию: Написать класс вектор через массив свойств.
Оба решения соответствуют поставленной задаче.
---
Что касается кода с классом TVectorClass, о нём могу сказать следующее. Парень молодец - написал реализацию. Уделил особенное внимание вопросам задания координат вектора при вводе с консоли - в методе VectorRead() анализируется строка с координатами вектора. Все основные действия он реализовал.
---
Из недочётов - класс TVectorClass не моделирует объект "вектор". На самом деле, класс TVectorClass представляет не отдельный вектор, а некий векторный процессор. Т. е., он хранит данные не одного вектора, а сразу трёх - двух векторов-операндов и третьего вектора-результата. Т. е., например, чтобы выполнить сложение двух векторов, надо координаты векторов загрузить в такой объект-процессор, затем вызвать метод сложения. - В результате в объекте-процессоре будут сформированы координаты вектора-результата, которые можно затем прочитать. Т. е. класс TVectorClass всё делает внутри себя, новые объекты не порождаются. - Это результат неверного архитектурного подхода.
Кроме этого, например, результат расчёта скалярного произведения векторов хранится в поле Multitude. Это поле расположено в разделе public. Это означает, что пользователь класса может сам вписать в это поле какие-то данные. Что может привести к противоречивости данных. Поэтому это поле следует спрятать. И внешний доступ к нему разрешить только на чтение.
Ещё опаснее то, что в разделе public расположено поле VectorLong - длина вектора. Если пользователь класса запишет в него значение - это не приведёт к физическому изменению длины вектора. А значит может привести к ошибкам. Это поле тоже следует переместить в раздел private. И внешний доступ к нему тоже должен быть только на чтение.
В код метода VectorRead() добавлен совершенно не нужный здесь вызов конструктора родительского класса.
Delphi
1
2
3
4
5
6
7
procedure TVectorClass.VectorRead(...);
... 
begin
 
  {Наследование всех функций конструктора Create класса TObject}
  inherited Create;
...
Да ещё комментарий написан весьма невразумительный. Вообще, что касается комментариев в коде класса TVectorClass - там надо многое подправить.
Например вот:
Delphi
1
2
    {Объявление деструктора создания объекта класса TVectorClass}
    destructor Destroy;
Комментарий противоречит сам себе: "Объявление деструктора создания объекта...". Лучше уж вообще такие комменты убрать.
Далее:
Delphi
1
2
    {Объявление конструктор создания объекта класса TVectorClass}
    constructor Create(EnteringVector1, EnteringVector2: string);
Здесь лучше написать кратко: "{Объявление конструктора}".
Delphi
1
2
    {Объявление функции сложения двух векторов}
    procedure Add;
Лучше так: "{Объявление метода сложения двух векторов}".
Delphi
1
2
3
4
5
6
{Описание деструктора объекта (вектора) класса TVectorClass}
destructor TVectorClass.Destroy;
begin
  {Наследование всех функций деструктора Destroy класса TObject}
  inherited Destroy;
end;
Здесь не "Наследование всех функций деструктора Destroy класса TObject", а: "Вызов деструктора Destroy() родительского класса (TObject)".
---

Не следует думать, что я придираюсь. Ещё раз повторю - парень молодец, написал реализацию, функциональную часть задачи решил. Но есть проблемы в архитектуре класса, комменты надо подправить и исправить прочие помарки - по крайней мере те, на которые я выше указал.

---

О проектировании.

Рассмотрим объект вектор. Начнём с данных. Данными вектора являются его координаты. Эти данные должны быть представлены в классе вектора и они должны быть защищены от свободно доступа. Это реализуется с помощью полей в разделе private. Соответственно должны быть определены методы для записи и чтения координат. Основные методы, которые работают с данными раздела private и которые понадобятся в будущем для разработки классов-потомков по возможности следует располагать в разделе protected. Раздел protected, по сути, должен содержать инструментарий для разработчика классов-потомков. В этом разделе могут присутствовать небезопасные методы и свойства, неправильное применение которых может привести к противоречивости данных. В раздел public следует помещать те методы, которые будут доступны программистам - пользователям класса. Кроме этого, многие методы из раздела public проектируются с таким расчётом, чтобы разработчики классов-потомков могли изменять их и усовершенствовать используя инструментарий из раздела protected. Поэтому эти методы вполне обосновано могут работать с данными класса через методы раздела protected, избегая прямого обращения к полям раздела private. Этот момент может быть оспорен, в случае, когда очень важен вопрос быстродействия. Но это уже вопрос конкретной задачи и конкретной реализации. Здесь надо подходить творчески и стараться одновременно решать задачу текущей реализации и думать о будущем - т. е., закладывать фундамент для будущих классов-потомков.
---
И так, данные вектора - это его координаты. Если имеем два набора координат - значит имеем два разных объекта. Объект-вектор должен уметь выполнять действия, определённые для векторов - например, скалярное произведение, сложение, вычитание. Причём, перечисленные действия выполняются над парой векторов - значит в этих действиях должны участвовать два объекта-вектора. Скалярное произведение должно возвращать в качестве результата вещественное число. А такие действия как сложение и вычитание векторов приводят к тому что появляется третий вектор - результат этих действий. Значит методы сложения и вычитания классе вектора должны возвращать новый объект-вектор.
Во время самой реализации класса вектора следует, по возможности, учитывать то что я написал выше о данных, методах, защищённости и о разделах private, protected, public.
Именно такую архитектуру я применил при реализации класса TVector.
В классе TVector имеется 4 перегружаемых конструктора для удобства задания вектора в различных ситуациях. Вызовы этих конструкторов продемонстрированы в программе. Данные в TVector весьма надёжно защищены. Небезопасное свойство ArrItems помещено в раздел protected. Это свойство даёт прямой доступ к хранилищу координат вектора. Поэтому оно доступно только для разработчиков классов-потомков - оно им может понадобится. Для пользователей класса это свойство недоступно. Действия над векторами реализованы в виде методв, объявленных в разделе private. Алгоритмы этих методов работают с данными вектора через методы раздела protected. Это гарантирует, что разработчики классов-потомков также смогут в большинстве случаев реализовать нужную им функциональность (данные раздела private для них будут недоступны).
Вызовы методов весьма лаконичны:
Delphi
1
2
3
4
5
6
7
8
//Получить скалярное произведение векторов V1 и V2:
ScalarMulti := V1.ScalarMultiply(V2);
 
//Вычесть из вектора V4 вектор V3 - в результате получается новый вектор VRes:
VRes := V4.Minus(V3);
 
//Сложить вектор V1 с вектором V2 - в результате получается новый вектор VRes:
VRes := V1.Plus(V2);
---
Кроме этого, в дополнение к классу TVector я реализовал класс TVectors - это коллекция для хранения векторов типа TVector. В коде программы приведён вариант кода для работы с коллекцией.
Класс коллекции является самостоятельным. Если он не нужен в проекте - его можно удалить.
---
Из критических замечаний к классу TVector, могу заметить, что есть "дыра" - пользователь класса всё-же может получить прямой доступ к хранилищу координат вектора. - Это возможно сделать во время создания вектора через третий вариант конструктора:
Delphi
1
2
3
4
5
constructor TVector.Create(const aArrItems : TArrNums);
begin
  inherited Create;
  FItems := aArrItems;
end;
Здесь в качестве параметра передаётся ссылка на динамический массив, содержащий координаты вектора. В теле конструктора эта ссылка напрямую записывается в поле FItems из раздела private. Это означает, что теперь из внешней среды по этой ссылке имеется доступ к данным раздела private. Это дыра. Именно поэтому, для надёжности, во внешнем коде написано так:
Delphi
1
2
3
4
5
6
  SetLength(ArrItems, M);
  for i := 0 to M - 1 do ArrItems[i] := i + 2;
  V3 := TVector.Create(ArrItems);
  //Вот здесь выполняется страховка - обнуляется внешняя ссылка на внутренние данные
  //вектора V3.
  ArrItems := nil;
Чтобы эту дыру закрыть, можно переписать код третьего конструктора так:
Delphi
1
2
3
4
5
6
7
8
9
constructor TVector.Create(const aArrItems : TArrNums);
var
  Len : Integer;
begin
  inherited Create;
  FItems := nil;
  Len := Length(aArrItems);
  if Len > 0 then FItems := Copy(aArrItems, 0, Len);
end;
Вот такой код защищает свои данные. Т. е., здесь создаётся новый массив с копией данных из aArrItems. И ссылка на этот новый массив записывается в поле FItems. Таким образом, внешний код не может получить доступ к скрытым данным экземпляра.
Минус этого кода только в том, что его быстродействие ниже, чем у незащищённого варианта. - Из за затрат времени на создание копии данных.
2
Заблокирован
11.06.2011, 00:22

Не по теме:

О_ониасилил



---
Mawrat: Материал непростой - здесь класс, вопросы архитектуры, динамические массивы. При изучении ООП надо стараться читать разные материалы, из разных источников и, может быть, разных авторов - постепенно расширяя своё понимание предмета.
0
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
17.06.2011, 13:16  [ТС]
Просто в порядке вопроса. А почему у меня не получается векторное произведени ?
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type
  TVector = class
    private
      FItems: array of real ;
                   public
      constructor Create(AItems: array of real);
      destructor Destroy; override;
            function VectorMulty(const A:TVector ) :TVector ;
            end;
                  ...
 function TVector.VectorMulty(const A:TVector ) :TVector ;
     var
     i:integer;
   begin
   if High(FItems) <> High(A.FItems) then
    ShowMessage('Îøèáêà. Ðàçìåðíîñòè âåêòîðîâ ðàçëè÷íû.') ;
     for i := 0 to High(FItems) do
     A.FItems[i]: = A.FItems[i]*FItems[i];
     Result:=A; // ошибка тут
   end;
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
17.06.2011, 13:59
Сначала замечания по коду.
Delphi
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
function TVector.VectorMulty(const A:TVector ) :TVector ;
var
  i:integer;
begin
  //При обнаружении несоответствия размерностей, код метода не будет прерван,
  //а пролжится. - Это приведёт, далее по коду, к ошибке чтения из памяти.
  if High(FItems) <> High(A.FItems) then
    ShowMessage('Ошибка. Размерности векторов различны.');
  
  //Код, представленный ниже, отработает. Но он введёт пользователя класса в заблуждение.
  //Параметр "A" в методе объявлен, как константа, поэтому ожидается, что вектор A не подвергнется
  //изменениям. Хотя это с технической точки зрения не так - потому что константой является только
  //ссылка на вектор, но не сами данные вектора, тем не менее, смысл этого метода подразумевает,
  //что параметр изменяться не будет ни в каких качествах.
  for i := 0 to High(FItems) do
    A.FItems[i]: = A.FItems[i]*FItems[i];
  
  //Вот здесь происходит следующее. Новый вектор не создаётся, вместо этого, ссылка
  //на уже существующий вектор, записывается в переменную Result, значение которой
  //затем будет возвращено в вызывающий код. Таким образом получается, что с одним
  //и тем же объектом связаны две переменные - A и Result. Причём, пользователь класса
  //не видит этого. Он, скорее всего, полагает, что метод ему вернул новый вектор.
  //Это в дальнейшем приведёт к ошибкам - если пользователь где-то вызовет деструктор
  //вектора, связанного через Result, то после этого попытка обратиться к данным
  //вектора, связанного через A приведёт к ошибке - т. к. этого вектора уже не существует.
  //Поэтому, надо создавать новый вектор, а не переприсваивать ссылки 
  Result:=A; // ошибка тут
end;
Метод надо переписать таким образом:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Векторное произведение.
function TVector.VectorMulty(const A : TVector) : TVector;
var
  i, Len : Integer;
  Arr : array of real;
begin
  if (A = nil) then
    raise Exception.Create(SelfName + '. Ошибка! A = nil.')
  ;
  if Count <> A.Count then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  //Размерность вектора (количество элементов вектора).
  Len := Length(FItems);
  //Создаём массив элементов для нового вектора.
  SetLength(Arr, Len);
  //Создаём новый вектор.
  Result := TVector.Create(Arr);
  //Вычисляем элементы и записываем их в новый вектор.
  for i := 0 to Len - 1 do
    Result.FItems[i] := FItems[i] * A.FItems[i]
  ;
end;
В том коде, который я в прежних сообщениях выкладывал, можно реализовать метод так:
Delphi
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
//Напомню - в классе вектора определён такой конструктор:
constructor TVector.Create(const aCount: Integer);
const
  selfName = 'TVector.Create()';
begin
  if aCount < 0 then
    raise Exception.Create(SelfName + '. Ошибка! Вектор не может иметь отрицательную размерность.')
  ;
  inherited Create;
  SetLength(FItems, aCount);
end;
 
//Векторное произведение.
function TVector.VectorMulty(const aVector : TVector) : TVector;
var
  i, Len : Integer;
begin
  if (aVector = nil) then
    raise Exception.Create(SelfName + '. Ошибка! aVector = nil.')
  ;
  if Count <> aVector.Count then
    raise Exception.Create(SelfName + '. Ошибка! Размерности векторов различны.')
  ;
  //Размерность вектора (количество элементов вектора).
  Len := Count;
  //Создаём новый вектор с размерностью, равной Len.
  Result := TVector.Create(Len);
  //Вычисляем элементы и записываем их в новый вектор.
  for i := 0 to Len - 1 do
    Result.Items[i] := Items[i] * aVector.Items[i]
  ;
end;
1
5 / 5 / 1
Регистрация: 21.11.2009
Сообщений: 110
17.06.2011, 14:08  [ТС]
А как его вывесив Edit ? Edit4.Text:=FloatToStr(VectorMulty) Так ?
0
 Аватар для Mawrat
13117 / 5898 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
17.06.2011, 14:22
Вот распечатывать его придётся с помощью перебора всех элементов вектора.
Если взять мой код - там для этого есть специальное свойство у вектора: TVector.AsString. В этом случае распечатка будет выглядеть так:
Delphi
1
2
3
4
...
  VRes := V1.VectorMulty(V2);
  Memo1.Lines.Add('Векторное произведение векторов V1 и V2 равно: ' + VRes.AsString);
...
Цитата Сообщение от Beren Посмотреть сообщение
Edit4.Text:=FloatToStr(VectorMulty)
Это для скалярного произведения подойдёт - потому что скалярное произведение это число вещественного типа. А результат векторного призведения является вектором.
---
Реализация свойства TVector.AsString:
Delphi
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
unit UVector;
 
interface
...
type
  TArrNums = array of Extended;
 
  //Класс: вектор.
  TVector = class(TObject)
  private
    FItems : TArrNums;
  protected
  ...
    function ToString : String; virtual;
  ...
  public
  ...
    property AsString : String read ToString;
  ...
  end;
...
implementation
...
function TVector.ToString: String;
var
  i, h : Integer;
begin
  Result := '';
  h := High(FItems);
  for i := 0 to h do begin
    if Result <> '' then Result := Result + '; ';
    Result := Result + FloatToStr(FItems[i]);
  end;
  Result := '(' + Result + ')';
end;
...
end.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.06.2011, 14:22

Написать комментарии к коду
Опишите какая строчка что выполняет ( не по блокам а именно по строчкам желательно) Магический Квадрат var Form3: TForm3; ...

Нужны комментарии к коду.
program otcht; type otch=record grupp:string; pred:string; kol:integer; pt:integer; ch:integer; tr:integer; dv:integer; ...

Дайте комментарии к коду
unit UnitMainForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,...

Нужны комментарии к коду
treeview1.Items.Item.Selected:=true ; Sleep(1500); CreateSemaphore(nil,0,1,'compdevice'); можете объяснить досконально...

Гаммирование, нужны комментарии к коду
Может кто расшифровать, как эта программа работает? var s,nabor_cifr:string; a,b:Integer; procedure...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru