Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.01.02;
Скачать: CL | DM;

Вниз

Как создать объект по имени его класса   Найти похожие ветки 

 
Чайник ©   (2004-12-15 18:43) [0]

У меня создан базовый класс типа TBlock = class(TComponent), и ряд производных от него классов вида TBlock1 = class(TBlock), TBlock2 и т.д. Как в программе создать объект конкретного класса, если я знаю его имя (имя сидит в строке вроде NewBlock = "TBlock1" : string)?


 
Суслик ©   (2004-12-15 18:47) [1]

изучай registerclass + findclass


 
Чайник ©   (2004-12-15 18:57) [2]

Изучаю.
Каждый модуль с описанием класса имеет секцию

 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. Почему?


 
jack128 ©   (2004-12-15 19:11) [3]

а чему равно newBlock на момент вызова??
Когда вызывается процедура добавления? Случайно не в секции ининциализации?
а если так  tmpBlockClass := TBlockClass(FindClass("TBlock1")); то работает??


 
Чайник ©   (2004-12-15 19:17) [4]

>а чему равно newBlock на момент вызова??
newBlock содержит имя класса;
>Когда вызывается процедура добавления? Случайно не в секции ининциализации?  - нет, из процедуры.
>а если так  tmpBlockClass := TBlockClass(FindClass("TBlock1")); то работает??
нет, и так не работает.


 
jack128 ©   (2004-12-15 19:20) [5]

хм. Больше мыслкй нет.  Отладчиком пройдись, что еще можно посоветовать...


 
Чайник ©   (2004-12-15 19:34) [6]

Опа!
У меня секция initialization не выполняется! Что за новости???


 
Sergey_Masloff   (2004-12-15 19:53) [7]

Чайник ©   (15.12.04 19:34) [6]
>У меня секция initialization не выполняется! Что за новости???
Значит этого модуля в USES нигде нет. Проверь?


 
Чайник ©   (2004-12-15 20:31) [8]

Вы будете смеяться, но теперь не выполняется секция finalization.
Чтобы это значило?
Кстати, а она всегда должна выполняться?


 
Sergey_Masloff   (2004-12-15 20:46) [9]

Вобщем, ничего не понятно. Тебе нужно что-то типа этого?

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 22:27) [10]

Прошу прощения, вынужденно отвлекся от занимательной дискуссии.

>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


 
Чайник ©   (2004-12-15 22:36) [11]

Ответ на собственный вопрос:
>Вы будете смеяться, но теперь не выполняется секция finalization.
>Чтобы это значило?
>Кстати, а она всегда должна выполняться?

У меня для отладки туда воткнуто ShowMessage("finalization");

Так вот ShowMessage отображается, только тотчас исчезает.


 
vuk ©   (2004-12-15 22:46) [12]

to Чайник ©   (15.12.04 22:27) [10]:
>так вот, мне нужно, чтобы вызывался конструктор Create именно
>конкретного производного класса (TBlock1 или TBlock2 или
>TBlockN), а не родительского TBlock.
Конструктор сделайте виртуальным. Как, например, это у TComponent сделано.


 
Sergey_Masloff   (2004-12-15 22:48) [13]

Перепишем 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 не забыли в иерархии?


 
Zacho ©   (2004-12-15 22:48) [14]

Чайник ©   (15.12.04 22:27) [10]

Приведи свой код полностью. А то есть у меня некоторые подозрения, да телепатировать лень :)


 
Sergey_Masloff   (2004-12-15 22:50) [15]

vuk ©   (15.12.04 22:46) [12]
>Конструктор сделайте виртуальным. Как, например, это у >TComponent сделано.
Это все потомки TComponent наверное где-то виртуальный конструктор заместили статическим. Вобщем код надо смотреть подробнее.


 
Чайник ©   (2004-12-15 22:51) [16]

Ура! Заработало! (с) Матроскин.

Работающий вариант:


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 := и т.д.



 
vuk ©   (2004-12-15 22:53) [17]

to Sergey_Masloff   (15.12.04 22:50) [15]:
>Это все потомки TComponent наверное где-то виртуальный
>конструктор заместили статическим.
Ну тогда просто override дописать. Сути это не меняет. Либо виртуальный конструктор отсутствует либо определен новый с другой сигнатурой. Другим путем такого эффекта не добиться. А что там на самом деле происходит - фиг его знает. Кода нет, а телепаты в отпуске.


 
Чайник ©   (2004-12-15 22:53) [18]

Кстати, а оно обязательно надо:

finalization

 UnRegisterClass(TBlockCylinder2Dsimm);


 
Sergey_Masloff   (2004-12-15 22:59) [19]

Чайник ©   (15.12.04 22:53) [18]
>Кстати, а оно обязательно надо:
>finalization
> UnRegisterClass(TBlockCylinder2Dsimm);
Не надо. Это можно сделать в коде программы для высвобождения ресурсов но не в финализации - все равно все высвободится автоматически.


 
Чайник ©   (2004-12-15 23:09) [20]

> Sergey_Masloff   (15.12.04 22:59) [19]

Спасибо



Страницы: 1 вся ветка

Текущий архив: 2005.01.02;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.045 c
14-1102758304
Vasya.ru
2004-12-11 12:45
2005.01.02
А где можно найти что - то вроде "Единой базы процедур и функций"


4-1100584362
paa
2004-11-16 08:52
2005.01.02
Узнать имя DLL которую загрузил мой процесс


9-1093532389
miek
2004-08-26 18:59
2005.01.02
гляньте на новую техно-демку


14-1102618544
Чеширский_Кот
2004-12-09 21:55
2005.01.02
Слепой музыкант - настоящий гений


14-1102662547
Cosinus
2004-12-10 10:09
2005.01.02
Как разметить диск под FAT32, если он сейчас NTFS? Под ДОС.