Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конвертация строк 
:(
    Опции темы
CodeMonkey
Дата 12.5.2011, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Цитата(PsiMagistr @  12.5.2011,  14:28 Найти цитируемый пост)
А если встречаются не строковые? Вот например у меня там есть интегровый тип


Integer и вовсе не динамический тип. Он уйдёт вместе с объектом. 

Объекты грубо можно считать расширенными записями. Вы же не удаляете в записи каждое Integer поле индивидуально?

Вот ежели вы GetMem-ом выделите память и сохраните в указателе-поле объекта - вот это другое дело. 

Цитата(PsiMagistr @  12.5.2011,  14:28 Найти цитируемый пост)
Не совсем так. Я слышал, что ежели мы собираемся серилизовывать объект, то свойства необходимы. Причем  в секции published 


В одну кучу не нужно смешивать: "наличие/отсутствие свойства" и "если свойство есть, то с чем работать: с полем или свойством". Оригинальный вопрос звучал так: 
Цитата(PsiMagistr @  12.5.2011,  10:16 Найти цитируемый пост)
Возможно ли в конструкторе обращение не к полям а к свойствам


Здесь нет ни слова про "необходимость" или "обходимость" свойств. Вопрос про то, можно ли обращаться к свойствам из конструктора. На этот вопрос я и отвечал.

Цитата(PsiMagistr @  12.5.2011,  14:47 Найти цитируемый пост)
А что же его освобождает окромя деструктора?


Магия компилятора. Если вы посмотрите на деструктор TObject (базовый объект, который является предком любого класса в Delphi), то увидите, что его деструктор пуст, ничего не делает вовсе. 

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

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

Технически, на уровне ассемблера - таки да, эту работу выполняет конструктор и деструктор. Но на уровне языка ВУ это так не выглядит.

Это сообщение отредактировал(а) CodeMonkey - 12.5.2011, 19:29


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
northener
Дата 13.5.2011, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(CodeMonkey @  12.5.2011,  19:29 Найти цитируемый пост)
В Delphi выделение и освобождение памяти под объект занимается магия компилятора

Это стоило бы выделить жирным шрифтом. Имхо.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
PsiMagistr
Дата 13.5.2011, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Ребята, 

Решаю продолжить свои зеленые вопросы по ООП. А то из-за плохого знания предмета, выйдет сплошная сериализация сюрреализация. Да и продираться сквозь материал надо. Материал тяжелый для (моего) понимания, а на вооружении у меня только книги.

Сердечно благодарю CodeMonkey и всех остальных откликающихся.

Итак:

1) Верно ли 

что для перекрытия родительского метода в классе-потомке используется директива override тогда и только тогда, когда

Метод потомка не только имеет одинаковое имя, но и одинаковый набор параметров, передаваемых в метод? Т.е. процедура является полным близнецом. Если набор параметров различен, ничего делать не нужно?

2) overload пишется тогда, когда мы хотим использовать два разных метода с одинаковыми именами, разным набором параметров и расположенных на одном иерархическом уровне. Если на разных, то это связь предок-потомок и нужен override[B] для перекрытия родительского (сам родительский при этом объявим виртуальным).


3) В чем разница между  [b]overload
 и reitroduce. Не могу уловить, хоть ты разбейся. )))



4) Верно ли утверждение, что деструкторы пишутся если в работе класса каким либо образом участвуют др. объекты? Т.е. в основном, чтобы их (эти другие) гасить. Например какое-либо поле определенно объектом. Или внутри метода объявлена переменная-указатель-на-объект? Много ли вообще существует НЕ-автофинализируемых типов? Я знаю что даже динам-массивы магия компилятора освобождает.

Давеча попалась на глаза книга "Искусство создания компонентов Дельфи". Некто Валерий Фаронов. Утверждение там такое (цитата):

"Методы класса не должны обращаться к полям, так как в общем случае они вызываются без (!) создания объекта, а следовательно в момент вызова полей просто не существует"...

Постойте, как это методы не должны обращаться к полям? Они же только и делают,  что обращаются. Иначе зачем они вообще нужны, если не для работы над полями?

Лично я пока только один метод знаю, который способен вне объекта вызываться - constructor.

   


Это сообщение отредактировал(а) PsiMagistr - 13.5.2011, 09:42


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
PsiMagistr
Дата 13.5.2011, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Такой вопрос еще. Создал я класс - потомок от некоего класса. У того некоторый метод. Мне от него ни холодно, ни жарко и я пишу свой с тем же именем но с др набором параметрофф.

Теперь у моего класса два метода от предка и собственный. 

Я так понял надо overload своему методу писать, если хочу в проге оба метода использовать?  

А если только один хочу, свой собственный, то не надо...

Так я понимаю.




--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
PsiMagistr
Дата 13.5.2011, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Очень любопытно. Выходит конструктор TObject  НЕвиртуален.

Код

implementation

{$R *.dfm}

Constructor MyClass.Create;
begin
inherited Create;
ShowMessage('Вызываю конструктор');
end;

Destructor MyClass.Destroy;
begin
ShowMessage('Вызываю деструктор');
inherited Destroy;
end;



procedure TForm1.Button3Click(Sender: TObject);
var M:MyClass;
begin
 M:=MyClass.Create; //Несмотря на то, что конструктор не виртуален-оверрайден, вызывается именно МОЙ вариант конструктора.
 M.Free; // С деструктором такие фокусы не проходят, надо оверрайдить. Почему? Потому, что деструктор вызывается через метод предка Free, что ли?
end;


Это сообщение отредактировал(а) PsiMagistr - 13.5.2011, 10:38


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 13.5.2011, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Рекомендую к прочтениею: http://www.delphikingdom.ru/lyceum/seminar.asp?ID=6

Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
1) Верно ли 

что для перекрытия родительского метода в классе-потомке используется директива override тогда и только тогда, когда

Метод потомка не только имеет одинаковое имя, но и одинаковый набор параметров, передаваемых в метод? Т.е. процедура является полным близнецом. Если набор параметров различен, ничего делать не нужно?


Нет. Директива override используется для введения новой версии виртуального метода. И, таки да, если это происходит, прототип должен полностью совпадать.

А для простого перекрытия override не нужен - просто пишем новый метод.

Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
2) overload пишется тогда, когда мы хотим использовать два разных метода с одинаковыми именами, разным набором параметров и расположенных на одном иерархическом уровне


Да. И это применимо не только к методам, но и обычным процедурам, например:
Код
function FloatToStr(Value: Extended): string; overload; 
function FloatToStr(Value: Extended;  const AFormatSettings: TFormatSettings): string; overload;


Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
Если на разных, то это связь предок-потомок и нужен override для перекрытия родительского (сам родительский при этом объявим виртуальным).


Он может, но вовсе не обязан быть виртуальным. Соответственно, override будет указываться или нет, смотря по тому, что мы в итоге решим.

Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
3) В чем разница между  [b]overload и reitroduce. Не могу уловить, хоть ты разбейся. )))


overload с reitroduce не связан никак, а вот override и reitroduce - понятия близкие. override "продолжает" цепочку наследования, вводя новый вариант виртуального метода. reitroduce "прерывает" цепочку наследования, "замещает" метод, вводя новый, который никак не связан с унаследованным виртуальным. reitroduce используется очень редко и только в одном случае: у тебя в предке есть виртуальный метод, но в твоём классе и любых его наследниках этот метод не нужен. Но зато у тебя есть потребность создать новый метод, который было бы очень удобно назвать так же, как и тот унаследованный виртуальный. Вот и вводишь ты метод и пишешь reintroduce.

Иногда использование reitroduce говорит о допущенных ошибках при проектировании иерархии.

Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
4) Верно ли утверждение, что деструкторы пишутся если в работе класса каким либо образом участвуют др. объекты? Т.е. в основном, чтобы их (эти другие) гасить. Например какое-либо поле определенно объектом. Или внутри метода объявлена переменная-указатель-на-объект? Много ли вообще существует НЕ-автофинализируемых типов? Я знаю что даже динам-массивы магия компилятора освобождает.


Деструктор нужен когда ему есть что делать. Удалить поле объекта. Раз-регистрировать элемент из его контейнера при удалении. Закрыть открытый объектом файл. И т.п. В остальных случаях деструктор не нужен.

К автофинализируемым типам в Delphi очевидным образом относятся все статические (просто потому, что они не нуждаются в финализации): Integer, записи и т.п., а кроме них: строки (String, AnsiString, UnicodeString, WideString), интерфейсы (IInterface, IDispatch, да и вообще любые), динамические массивы, варианты (Variant и OleVariant). Вроде, никого не забыл.

Все прочие типы к таковым не относятся. К примеру, объекты, динамически выделенная память (GetMem, AllocMem, New).

Но даже если память освобождается - автоматом это не значит, что делать нечего. К примеру, твой Integer может быть описателем открытого через CreateFile файла - и тогда в деструкторе файл надо закрыть.

Цитата(PsiMagistr @  13.5.2011,  09:44 Найти цитируемый пост)
Давеча попалась на глаза книга "Искусство создания компонентов Дельфи". Некто Валерий Фаронов. Утверждение там такое (цитата):

"Методы класса не должны обращаться к полям, так как в общем случае они вызываются без (!) создания объекта, а следовательно в момент вызова полей просто не существует"...

Постойте, как это методы не должны обращаться к полям? Они же только и делают,  что обращаются. Иначе зачем они вообще нужны, если не для работы над полями?


Вы путаете методы объекта и методы класса. Методы объекта - это:

Код
type
  TMyObj = class
  private
    FField: Integer;
  public
    procedure DoSomething;
  end;

procedure TMyObj.DoSomething;
begin
  FField := 0;
end;

...

var
  O: TMyObj;
begin
  O := TMyObj.Create;
  O.DoSomething;
  ...

end;


Методы класса - это:
Код
type
  TMyObj = class
  private
    FField: Integer;
  public
    class procedure DoSomething;
  end;

class procedure TMyObj.DoSomething;
begin
  FField := 0; // <- не скомпилируется
end;

...

begin
  TMyObj.DoSomething; // вызов метода без создания объекта
end;


Цитата(PsiMagistr @  13.5.2011,  10:22 Найти цитируемый пост)
Теперь у моего класса два метода от предка и собственный. 

Я так понял надо overload своему методу писать, если хочу в проге оба метода использовать?  


Не обязательно. Если ты хочешь сделать два метода доступными - то надо оба их объявить с overload. Если унаследованный объявлен без overload - надо в своём классе его продублировать с overload и вызвать унаследованный. Ну а в своём варианте делать что хочешь.

Цитата(PsiMagistr @  13.5.2011,  10:22 Найти цитируемый пост)
А если только один хочу, свой собственный, то не надо...


Да.

Цитата(PsiMagistr @  13.5.2011,  11:35 Найти цитируемый пост)
Несмотря на то, что конструктор не виртуален-оверрайден, вызывается именно МОЙ вариант конструктора.


По той простой причине, что вызываешь ты его через свой класс: [B]MyClass.Create.

Цитата(PsiMagistr @  13.5.2011,  11:35 Найти цитируемый пост)
С деструктором такие фокусы не проходят, надо оверрайдить. Почему? Потому, что деструктор вызывается через метод предка Free, что ли?


Если ты вызываешь деструктор напрямую - то он может быть не виртуальным. И иногда (очень редко) так делают для хитрых целей.

Но ты вызываешь деструктор через метод-обёртку Free, которая реализована у TObject. Т.е. если деструктор не виртуальный, то единственный деструктор, который сможет вызвать Free при любом раскладе будет деструктор TObject. В этом и смысл виртуальности: что при вызове из базового класса, используется метод потомка.

Это сообщение отредактировал(а) CodeMonkey - 13.5.2011, 13:37


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 16.5.2011, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



CodeMonkey,  Верно ли  я понимаю, что деструктор оверрайдится практически всегда. Ведь Free, как правило принадлежит предку, а он должен вызывать новую версию деструктора.


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 16.5.2011, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Да, всегда.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 16.5.2011, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Странное дело. Просто пытаюсь разобраться. Не лупите сильно, ладно? smile

Создаю объект А. Владелец этого объекта (Owner) - форма. Объект класса TComponent

Создаю объект Б. класс  TComponent.  Внимание - Владелец - объект А.

Заполняю свойства объекта А.

Заполняю свойства объекта Б.

Открываю файл, записываю данные объекта А (WriteComponent)

При записи объект А должен потянуть за собой и детище - объект Б. Тянет же за собою форма все остальные компоненты.

Т.е. файл должен содержать и данные А, и данные Б.

Не тут то было...

При записи в файл вижу данные только объекта А.








Это сообщение отредактировал(а) PsiMagistr - 16.5.2011, 12:34


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 17.5.2011, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Как я уже говорил: навскидку с TComponent я не отвечу. Надо время, чтобы смотреть и разбираться. А его у меня нет.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 17.5.2011, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Понятно. Ничего страшного. Спасибо. Я пока сижу, с TPresistent


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
PsiMagistr
Дата 18.5.2011, 07:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Вот в чем оказывается дело:

Об ответственности за сериализацию

Не пугайтесь названия этого раздела. Речь пойдёт всего лишь о том, как сделать так, чтобы компонент записывал вместе с собой в поток другие.

Было бы ошибкой предполагать, что компонент сериализует то, чем он владеет. Владение и ответственность за сериализацию – это разные отношения, и по умолчанию компонент не сериализует вместе с собой ничего. Впрочем, в VCL есть два класса-наследника TComponent, которые сериализуют именно то, чем владеют: это TForm и TDataModule, и если посмотреть их исходный код, можно увидеть, что в них переопределён protected-метод TComponent.GetChildren.

procedure GetChildren(Proc: TGetChildProc; Root: TComponent); dynamic;

где

type TGetChildProc = procedure (Child: TComponent) of object;

GetChildren – переопределяемый метод, в классе TComponent он пуст. Он автоматически вызывается в тот момент, когда система сериализации хочет опросить компонент о том, какие ещё компоненты нужно сохранять. В свою очередь, те компоненты тоже будут опрошены, и т. д. В аргумент Root передаётся ссылка на компонент, для которого когда-то был запущен метод TStream.WriteComponent, и если мы пришли к сериализации данного компонента через один или несколько «каскадов», Root<>Self.

В GetChildren от программиста требуется, чтобы он один или несколько раз вызвал Proc, указывая в качестве аргумента те компоненты, которые нужно сериализовать вместе с данным. Например, в классах TForm и TDataModule в GetChildren организуется цикл по элементам массива TComponent.Components:

var
  I: Integer;
  OwnedComponent: TComponent;
begin
  inherited GetChildren(Proc, Root);
  if Root = Self then
    for I := 0 to ComponentCount - 1 do
    begin
      OwnedComponent := Components[I];
      if not OwnedComponent.HasParent then Proc(OwnedComponent);
    end;
end;

В методе же TCustomActionList.GetChildren имеется цикл по Action’ам, которые входят в данный ActionList.

Как выглядит результат работы GetChildren в dfm-формате, мы уже видели: объект сохраняется как бы «внутри» того, который отвечает за его сериализацию. Так, на представленном выше фрагменте dfm-файла, Form1 отвечает за сериализацию Button1, Button2 и ActionList1, а ActionList1 – за сериализацию Action1 и Action2.

Во время же загрузки из потока компонент может узнать о том, кто отвечал за его сериализацию, и предпринять соответствующие действия. Для этого надо переопределить метод

procedure SetParentComponent(Value: TComponent); dynamic;

Например, TAction таким образом при десериализации может зарегистрировать себя в сериализовавшем его ActionList’е.

Сериализацию наладил, содрав код в котором смыслю мало что...

Дело за десериализацией.


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0892 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.