Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 03.03.2015, 23:16
Alex55V Alex55V вне форума
Прохожий
 
Регистрация: 01.10.2014
Сообщения: 10
Версия Delphi: Delphi 2010
Репутация: 10
По умолчанию Несовместимость типов

Уважаемые форумчане.
Вот мой класс (заготовка). Класс будет работать с динамическим массивом
Код:
unit U_Event;

interface

type
  TEvent = record
    F_1 : string;
    F_2 : integer;
    F_3 : string;
  end;

type
  TEventList = class(TObject)
  private
    fCount: integer;
    fItemIndex: integer;
    function GetCount :integer;
    function SetCount(NewCount: integer): boolean;

  public
    items : array of TEvent;
    constructor Create;
    property Count : integer read GetCount Write SetCount;
    destructor free; virtual;
  end;

implementation
//                 Конструктор
constructor TEventList.Create;
begin
  inherited;
  fItemIndex := -1;
  fCount := 0;
  SetLength(items,fCount);
end;
//                 Изменение размеров массива событий
function TEventList.SetCount(NewCount: integer): boolean;
begin
  Result := True;
  if NewCount < 0 then
    begin
      Result := False;
      NewCount := 0;
    end;
  fCount := NewCount;
  SetLength(items,fCount);
end;
//                 Чтение размера массива событий
function TEventList.GetCount: integer;
begin
  result := fCount;
end;
//                 Разрушение объекта
destructor TEventList.free;
begin
  SetLength(items,0);
  Inherited Destroy;
end;
end.

Ошибка в строке 23. Говорит о несовместимости типов. Скорее всего из-за того, что тип функции SetCount - Boolean а тип Count - integer.
Как исправить ошибку, не меняя определения функции, или не получится?
Ответить с цитированием
  #2  
Старый 03.03.2015, 23:45
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Определил свойство Count как Integer, так будь добр соблюдать его.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #3  
Старый 04.03.2015, 00:09
Alex55V Alex55V вне форума
Прохожий
 
Регистрация: 01.10.2014
Сообщения: 10
Версия Delphi: Delphi 2010
Репутация: 10
По умолчанию

То, что соответствие типов надо соблюдать, даже я знаю. Только вот в вызывающей программе хотелось бы иметь возможность написать:
Код:
List := TEventList.Create;
....
....
....
if List.Coun(N) then ShowMessage('Размер массива изменён'),
Как реализовать свою хотелку? Вот в чём вопрос.....

Последний раз редактировалось Alex55V, 04.03.2015 в 00:30.
Ответить с цитированием
  #4  
Старый 04.03.2015, 01:16
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

В таком виде - никак.
Т.е. SetCount д.б. процедурой (не возвращать никаких значений).
Если очень хочется отлавливать ошибку - выбрасывай исключение при ошибке изменения размера массива. Либо сделай само св-во только для чтения и public метод для изменения размера массива.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Alex55V (04.03.2015)
  #5  
Старый 04.03.2015, 09:58
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

и деструктор не должен называться free !
free -это невиртуальная функция класса TObject, которая сама вызывает Destroy. поэтому нужно делать так

Код:
type
  TEventList = class(TObject)
....
   destructor Destroy; virtual;
  end;
и
Код:
destructor TEventList.Destroy;
begin
  SetLength(items,0);
  Inherited Destroy;
end;
И вот это
Код:
  SetLength(items,0);
в деструкторе делать необязательно.
Если в деструкторе больше кода не будет, то его можно совсем исключить.
Ответить с цитированием
  #6  
Старый 04.03.2015, 16:00
Alex55V Alex55V вне форума
Прохожий
 
Регистрация: 01.10.2014
Сообщения: 10
Версия Delphi: Delphi 2010
Репутация: 10
Счастье

Цитата:
Сообщение от lmikle
Т.е. SetCount д.б. процедурой.
А я ведь Вам не поверил.... Попробовал изменить тип функции с boolean на integer и вообще отказаться от указания типа функции... Процедура - работает. Функция - ни в каком виде. Вывод: ошибка ни в типе данных, а в кривом использовании property. Правильно понял?
Цитата:
Сообщение от icWasya
free -это невиртуальная функция класса TObject, которая сама вызывает Destroy.
free невиртуальная функция класса TObject, проверяет наличие удаляемого объекта, и если он существует, то сама вызывает Destroy. В крайнем случае так написано в книгах. Не исключаю что при таком вызове Destroy могут быть подводные камни. Тогда какие.

Теперь просьбы
Хотелось бы чтобы Ваши ответы были ни столь подробны. Лучше лишний раз переспрошу.
Я могу путаться в понятиях и определениях. Огромная просьба поправляйте.
Научите определять всю ли память освободила программа, после завершения своей работы
Ответить с цитированием
  #7  
Старый 04.03.2015, 18:19
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Цитата:
ошибка не в типе данных, а в кривом использовании property. Правильно понял?
Правильно.
Цитата:
Не исключаю что при таком вызове Destroy могут быть подводные камни. Тогда какие?
ВСЕ классы используют именно этот механизм. А вот если сделать так, как сделали Вы...
Цитата:
так написано в книгах
в тех же книгах Вы увидите рекомендацию использовать FreeAndNil.
запример здесь - http://www.gunsmoker.ru/2009/04/freeandnil-free.html
Которая вызывает TObject.Free, и затем обнуляет поданый ей указатель.
А про Ваш free она ничего не знает и никогда его не вызовет.
Про SetLength в деструкторе.
В Delphi есть несколько категорий типов, которые имеют автоматическое время жизни. Это интерфейсы, строки, и всякие динамические массивы.
При входе в процедуру/функцию, в которой есть переменные таких типов, или созданию объекта/структуры, в котором есть поля таких типов, они автоматически инициализируются nil-ом, что в случае строк и массивов эквивалентно массиву нулевой длины.
И соответственно при выходе из процедуры/функции или уничтожению объекта/структуры, будут уничтожены и такие автоматические объекты.
В Вашеи случае в объекте типа TEventList есть поле типа динамический массив, а в структуре TEvent ести два поля типа String. При разрушении TEventList автоматически будет вызван финализатор для поля items, который сначала проведёт финализацию всех своих элеиентов, при этом в каждом уничтожатся строки F_1 и F_3, а затем будет уничтожен сам массив. Но не забывайте, что наследники TObject не имеют автоматического время жизни, по этому все созданные руками объекты нужно уничтожать самому.
Ответить с цитированием
Этот пользователь сказал Спасибо icWasya за это полезное сообщение:
Alex55V (04.03.2015)
  #8  
Старый 04.03.2015, 21:09
Alex55V Alex55V вне форума
Прохожий
 
Регистрация: 01.10.2014
Сообщения: 10
Версия Delphi: Delphi 2010
Репутация: 10
По умолчанию

icWasya у.
Спасибо за все Ваши разъяснения и ссылки. В связи с тем, что я пока чайник, и даже свисток имеется, то понял только общий смысл. Между прочим Вы ответили на вопросы, которые я хотел задать.
Ответить с цитированием
  #9  
Старый 05.03.2015, 06:41
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,015
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от Alex55V
А я ведь Вам не поверил.... Попробовал изменить тип функции с boolean на integer и вообще отказаться от указания типа функции... Процедура - работает. Функция - ни в каком виде. Вывод: ошибка ни в типе данных, а в кривом использовании property. Правильно понял?

А зря. Собственно, можно было бы и так догадаться.
Сеттер просто устанавливает значение аттрибуту (не путать со свойством) объекта. Там фунция просто не нужна, т.к. ей нечего возвращать. Если происходит ошибка, то надо просто выбрасывать исключение.
А сообщение об ошибке в типе данных связвно с тем, как данный механизм реализован внутри языка. Фактически там объявлены процедурные типы для геттера и сеттера и если реальная процедура/фунция по сигнатуре (не кидаться помидорами, знаю. что там не сигнатура, но так понятнее для начинающего) не совпадает с указанным типом, то выдается сообщение о несоответствии типов.

Последний раз редактировалось lmikle, 05.03.2015 в 06:44.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 02:19.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter