![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как создать объект по имени его класса [D6, WinXP]
Чайник © (2004-12-15 18:43:00)У меня создан базовый класс типа TBlock = class(TComponent), и ряд производных от него классов вида TBlock1 = class(TBlock), TBlock2 и т.д. Как в программе создать объект конкретного класса, если я знаю его имя (имя сидит в строке вроде NewBlock = 'TBlock1' : string)?
Чайник (2004-12-15 23:09:00) [1]> Sergey_Masloff (15.12.04 22:59) [19]
Спасибо
Sergey_Masloff (2004-12-15 22:59:00) [2]Чайник © (15.12.04 22:53) [18]
>Кстати, а оно обязательно надо:
>finalization
> UnRegisterClass(TBlockCylinder2Dsimm);
Не надо. Это можно сделать в коде программы для высвобождения ресурсов но не в финализации - все равно все высвободится автоматически.
Чайник (2004-12-15 22:53:00) [3]Кстати, а оно обязательно надо:
finalization
UnRegisterClass(TBlockCylinder2Dsimm);
vuk (2004-12-15 22:53:00) [4]to Sergey_Masloff (15.12.04 22:50) [15]:
>Это все потомки TComponent наверное где-то виртуальный
>конструктор заместили статическим.
Ну тогда просто override дописать. Сути это не меняет. Либо виртуальный конструктор отсутствует либо определен новый с другой сигнатурой. Другим путем такого эффекта не добиться. А что там на самом деле происходит - фиг его знает. Кода нет, а телепаты в отпуске.
Чайник (2004-12-15 22:51:00) [5]Ура! Заработало! (с) Матроскин.
Работающий вариант:
procedure TFEditor.btnBlockAddClick(Sender: TObject);
var tmpBlockClass : TBlockClass;
tmpBlockClassName : String;
...
tmpBlockClassName := ListNamesBlock[tmpNo].ClassName;
tmpBlockClass := TBlockClass(FindClass(tmpBlockClassName));
BlocksCount := BlocksCount + 1;
SetLength(Blocks, BlocksCount);
Blocks[BlocksCount-1] := tmpBlockClass.Create(Self);
Blocks[BlocksCount-1].Caption := и т.д.
Sergey_Masloff (2004-12-15 22:50:00) [6]vuk © (15.12.04 22:46) [12]
>Конструктор сделайте виртуальным. Как, например, это у >TComponent сделано.
Это все потомки TComponent наверное где-то виртуальный конструктор заместили статическим. Вобщем код надо смотреть подробнее.
Zacho (2004-12-15 22:48:00) [7]Чайник © (15.12.04 22:27) [10]
Приведи свой код полностью. А то есть у меня некоторые подозрения, да телепатировать лень :)
Sergey_Masloff (2004-12-15 22:48:00) [8]Перепишем Unit2
unit Unit2;
interface
uses Classes;
type
TBlock = class(TComponent)
protected
fData : String;
public
function GetName : String;
end;
TBlock1 = class(TBlock)
public
constructor Create(AOwner : TComponent); reintroduce; override;
end;
TBlock2 = class(TBlock)
public
constructor Create(AOwner : TComponent); reintroduce; override;
end;
implementation
{ TBlock1 }
{ TBlock }
function TBlock.GetName: String;
begin
result := fData;
end;
{ TBlock1 }
constructor TBlock1.Create(AOwner: TComponent);
begin
inherited;
fData := 'Block1 at service';
end;
{ TBlock2 }
constructor TBlock2.Create(AOwner: TComponent);
begin
inherited;
fData := 'Block2 at service';
end;
initialization
RegisterClasses([TBlock1, TBlock2]);
end.
При вводе имен разных блоков выдаются разные сообщения - т.е. конструкторы работают. Там нигде override не забыли в иерархии?
vuk (2004-12-15 22:46:00) [9]to Чайник © (15.12.04 22:27) [10]:
>так вот, мне нужно, чтобы вызывался конструктор Create именно
>конкретного производного класса (TBlock1 или TBlock2 или
>TBlockN), а не родительского TBlock.
Конструктор сделайте виртуальным. Как, например, это у TComponent сделано.
Чайник (2004-12-15 22:36:00) [10]Ответ на собственный вопрос:
>Вы будете смеяться, но теперь не выполняется секция finalization.
>Чтобы это значило?
>Кстати, а она всегда должна выполняться?
У меня для отладки туда воткнуто ShowMessage('finalization');
Так вот ShowMessage отображается, только тотчас исчезает.
Чайник (2004-12-15 22:27:00) [11]Прошу прощения, вынужденно отвлекся от занимательной дискуссии.
>Sergey_Masloff
У меня объявлен массив Blocks : array of TBlock; , так вот, мне нужно, чтобы вызывался конструктор Create именно конкретного производного класса (TBlock1 или TBlock2 или TBlockN), а не родительского TBlock.
Я пробовал по Вашему совету:
procedure TFEditor.btnBlockAddClick(Sender: TObject);
var tmpBlockClass : TComponentClass;
tmpBlock : Pointer;
...
tmpBlockClass := TComponentClass(GetClass(newBlock));
tmpBlock := tmpBlockClass.Create(Self);
Выполняется Create родительского класса, а не того, чье имя сидит в newBlock
Sergey_Masloff (2004-12-15 20:46:00) [12]Вобщем, ничего не понятно. Тебе нужно что-то типа этого?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
btCreate: TButton;
btClose: TButton;
procedure btCloseClick(Sender: TObject);
procedure btCreateClick(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.btCloseClick(Sender: TObject);
begin
Close();
end;
procedure TForm1.btCreateClick(Sender: TObject);
var
cls : TComponentClass;
ptr : Pointer;
begin
cls := TComponentClass(GetClass(Edit1.Text));
if Assigned(cls) then
try
ptr := cls.Create(Application);
ShowMessage(TBlock1(ptr).GetName);
finally
TObject(ptr).Free();
end else
ShowMessage('Класс не найден');end;
end.
//////// Unit2
unit Unit2;
interface
uses Classes;
type
TBlock = class(TComponent);
TBlock1 = class(TBlock)
public
function GetName : String;
end;
implementation
{ TBlock1 }
function TBlock1.GetName: String;
begin
Result := 'TBlok1 at your service!';
end;
initialization
RegisterClass(TBlock1);
end.
Форма с 2 кнопками и едитом. В едит вводишь TBlock1 получаешь строку возвращаемую TBlock1.GetName. Тебе это нужно
Чайник (2004-12-15 20:31:00) [13]Вы будете смеяться, но теперь не выполняется секция finalization.
Чтобы это значило?
Кстати, а она всегда должна выполняться?
Sergey_Masloff (2004-12-15 19:53:00) [14]Чайник © (15.12.04 19:34) [6]
>У меня секция initialization не выполняется! Что за новости???
Значит этого модуля в USES нигде нет. Проверь?
Чайник (2004-12-15 19:34:00) [15]Опа!
У меня секция initialization не выполняется! Что за новости???
jack128 (2004-12-15 19:20:00) [16]хм. Больше мыслкй нет. Отладчиком пройдись, что еще можно посоветовать...
Чайник (2004-12-15 19:17:00) [17]>а чему равно newBlock на момент вызова??
newBlock содержит имя класса;
>Когда вызывается процедура добавления? Случайно не в секции ининциализации? - нет, из процедуры.
>а если так tmpBlockClass := TBlockClass(FindClass('TBlock1')); то работает??
нет, и так не работает.
jack128 (2004-12-15 19:11:00) [18]а чему равно newBlock на момент вызова??
Когда вызывается процедура добавления? Случайно не в секции ининциализации?
а если так tmpBlockClass := TBlockClass(FindClass('TBlock1')); то работает??
Чайник (2004-12-15 18:57:00) [19]Изучаю.
Каждый модуль с описанием класса имеет секцию
initialization
RegisterClass(TBlock1);
Далее, в программе объявлен тип:
type TBlockClass = class of TBlock;
В процедуре добавления блока есть
var tmpBlockClass : TBlockClass;
tmpBlock : TBlock;
...
tmpBlockClass := TBlockClass(FindClass(newBlock));
tmpBlock := tmpBlockClass.Create(Self);
При запуске имею: Class TBlock1 not found. Почему?
Суслик (2004-12-15 18:47:00) [20]изучай registerclass + findclass