Форум: "Основная";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];
ВнизКакой тип имеет указатель на конструктор TObject? Найти похожие ветки
← →
alex_*** (2004-01-17 14:07) [0]Делаю некий константный массив адресов конструкторов объектов. Адреса хранятся в типе Pointer. Как потом из этой переменной вызвать конструктор на выполнение?
преобразование типа TFunc = class function s:String):TBaseFileAccess of object; не пропускает компилер.
а при таком: TFunc = function(s:String):TBaseFileAccess;
заходим в конструктор, но при переходе к первому оператору получаем AV.
Отсюда вопрос: Какой тип имееют указатели на конструкторы? В частности на конструктор TObject?
← →
Vuk (2004-01-17 14:18) [1]А зачем штаны-то через голову надевать? Может проще сделать виртуальный конструктор и хранить ссылки на классы?
← →
alex_*** (2004-01-17 14:22) [2]Так эти классы еще не созданы.. в константном массиве хранится информация о том какие классы можно создать
← →
alex_*** (2004-01-17 14:27) [3]В принципе можно сделать что-то типа такого:
function ( type: Integer ):TSomeBaseClass;
Begin
case type of
0: result := TClass1.Create();
1: result := TClass2.Create();
else
raise Exception.Create("..");
end;
End;
но все-таки интересно вызвать конструктор по его адресу...
← →
Vuk (2004-01-17 14:27) [4]>Так эти классы еще не созданы..
Еще раз читайте внимательно. Я говорю не о ссылках на экземпляры а о ссылках на классы. Читайте help на тему class references и constructors, там про виртуальные конструкторы тоже сказано. Смотрите также на RegisterClass и FindClass.
← →
alex_*** (2004-01-17 14:29) [5]OK. Сейчас посмотрю
← →
alex_*** (2004-01-17 15:15) [6]таки не понял что значит хранить ссылки на классы ((. Если бы на зкземпляры это одно, а здесь непонятно... Если через RegistarClass идти значит надо наследоваться от TPersistent. Теоретически же можно, зная адрес конструктора класса и его тип создать по нему класс. При этом не важно от чего наследуемся.
В итоге сделал через статическую ф-цию, которая вызывает конструктор в себе:
class function TTestAccess.CreateAccess(FileName:String):TBaseFileAccess;
begin
result := TTestAccess.Create(FileName);
end;
запоминаю её адрес в константе типа
function (FileName:String):TBaseFileAccess of object;
и она мне влет делает экземпляр класса когда нужно.
← →
Vuk (2004-01-17 15:34) [7]>таки не понял что значит хранить ссылки на классы ((
В простейшем варианте так:
var
ClassRef: TComponentClass;
ClassRef := TForm;
> Если через RegistarClass идти значит надо наследоваться от
>TPersistent.
В принципе, это не обязательно. Можно просто написать TPersistentClass(TMyClass) и регистрировать любые классы.
>Теоретически же можно, зная адрес конструктора класса и его тип
>создать по нему класс.
Ссылка на класс дает Вам доступ к функциям класса и виртуальным конструкторам без всяких извращений.
>При этом не важно от чего наследуемся.
Важно, т.к. конструкторы разных классов могут иметь различные наборы параметров. Виртуальные же конструкторы обеспечивают корректное конструирование классов через ссылку на класс.
← →
Vuk (2004-01-17 15:53) [8]>В принципе, это не обязательно. Можно просто написать
>TPersistentClass(TMyClass) и регистрировать любые классы.
Вот здесь я наврал. :o) Наследоваться, действительно, нужно от TPersistent. Я сейчас набросаю примерчик.
← →
Vuk (2004-01-17 15:57) [9]Вводите в строку имя одного из зарегистрированных классов, и смотрите, что получится. Лучше - с отладчиком и пошагово.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TSampleBaseClass = class of TSampleBase;
TSampleBase = class(TPersistent)
private
FInstanceName: string;
public
constructor Create(const AInstanceName: string); virtual;
procedure ShowInfo; virtual;
property InstanceName: string read FInstanceName;
end;
TSample1 = class(TSampleBase)
private
FIntProp: integer;
public
constructor Create(const AInstanceName: string); override;
procedure ShowInfo; override;
property IntProp: integer read FIntProp write FIntProp;
end;
TSample2 = class(TSampleBase)
private
FStrProp: string;
public
constructor Create(const AInstanceName: string); override;
procedure ShowInfo; override;
property StrProp: string read FStrProp write FStrProp;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TSampleBase }
constructor TSampleBase.Create(const AInstanceName: string);
begin
inherited Create;
FInstanceName := AInstanceName;
end;
procedure TSampleBase.ShowInfo;
begin
ShowMessage(Format( ""%s" is %s", [InstanceName, ClassName]));
end;
{ TSample1 }
constructor TSample1.Create(const AInstanceName: string);
begin
inherited Create(AInstanceName);
FIntProp := 0;
end;
procedure TSample1.ShowInfo;
begin
ShowMessage( Format( ""%s" is %s; %s=%d", [InstanceName, ClassName, "IntProp", FIntProp]));
end;
{ TSample2 }
constructor TSample2.Create(const AInstanceName: string);
begin
inherited Create(AInstanceName);
FStrProp := "Some value";
end;
procedure TSample2.ShowInfo;
begin
ShowMessage( Format( ""%s" is %s; %s=%s", [InstanceName, ClassName, "StrProp", FStrProp]));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ClassRef: TSampleBaseClass;
Instance: TSampleBase;
begin
ClassRef := TSampleBaseClass(GetClass(Edit1.Text));
if ClassRef <> nil then
begin
Instance := ClassRef.Create("TestInstance");
try
Instance.ShowInfo;
finally
Instance.Free;
end;
end;
end;
initialization
RegisterClasses([TSample1, TSample2]);
end.
← →
Vuk (2004-01-17 16:01) [10]Да, и еще. Список любых классов может хранить TClassList (модуль contnrs.pas).
← →
alex_*** (2004-01-17 17:14) [11]Прошу прощения за, возможное отсутствия у меня некоторых базовых знаний по VCL, но у меня возникли следующие вопросы:
Можно просто написать TPersistentClass(TMyClass) и регистрировать любые классы
Нельзя. У меня класс наследуется от TObject и при RegisterClass(TPersistentClass(TMyClass)) получаем AV. Я так понял при регистрации класса мы говорим системе что этот класс можно загрузить/сохранить в поток и конструктор имеет заранее обозначанный тип, т.е система знает как его создавать. При наследовании от TObject мы этой функциональности не имеем. И тип конструктора мне нужен свой.
Вопрос по ходу: Каким образом результат ф-ции GetClass можно превратить в экз. объекта?
Ссылка на класс дает Вам доступ к функциям класса ....
Для этого из ссылки надо создать экз. объекта, я так понял. Кстати, что тогда из себя физически представляет "ссылка на класс" (адресом конструктора не является)
В моем случае для основной программы известен базовый класс с виртуальными ф-ми и адреса конструкторов наследованных классов. При этом знаем какие пар-ры принимают конструкторы и типы конструкторов соотв. одинаковые. Теоретически можно же создать экз. унаследованного класса, зная какие пар-ры принимает конструктор?
Я так понимаю для системы конструкор это функция, которая возвращает указатель на определенный класс. Значит и вызвать его можно достаточно просто, создав указатель на функцию, записать в него нужный адрес и вызвать. Только вот компилятору я этого объяснить не смог ((.
← →
alex_*** (2004-01-17 17:16) [12]Спасибо.
пример сейчас посмотрю.. (я по модему соединяюсь время от времени и набивал в offline)
← →
Vuk (2004-01-17 17:43) [13]to alex_***:
>Нельзя.
Я ж сказал, что я там наврал и уже поправил сам себя. :o)
>Для этого из ссылки надо создать экз. объекта, я так понял.
Методы класса, они потому и являются методами класса, что доступны без создания экземпляра.
>Кстати, что тогда из себя физически представляет "ссылка на
>класс" (адресом конструктора не является)
Указатель на данные класса, которые генерирует компилятор.
>Я так понимаю для системы конструкор это функция, которая
>возвращает указатель на определенный класс.
В принципе да. Если конструктор класса TSomeClass имеет вид:
constructor Create(const SomeParam: string);
то это примерно соответствует:
function Create(self: TSomeClassRef; const SomeParam: string): TSomeClass;
где TSomeClassRef - ссылка на класс, который конструируется.
>Значит и вызвать его можно достаточно просто, создав указатель
>на функцию, записать в него нужный адрес и вызвать.
А вот это просто так не совсем получится - компилятор генерирует специальный код для вызовов конструкторов.
← →
alex_*** (2004-01-19 16:35) [14]to Vuk: спасибо за пример.
p.s.
судя по CPU View конструктор действительно не функция и вызвать его как ф-цию не получится (по кр. мере в лоб) (((
← →
jack128 (2004-01-19 17:11) [15]
> судя по CPU View конструктор действительно не функция
Действительно, это не функция - это метод. ;-) Более, того дельфя использует спец флаг, для указания, как конструктор вызывать, как классовый метод (при этом создается экземпляр класса) или как обычный метод.
← →
alex_*** (2004-01-19 17:15) [16]ну я про этот флаг и говорю.
← →
Erik (2004-01-19 17:21) [17]Я делал задачу один к одному.
UserForm = (frmAruteluSisestamine, frmAruteluEttevalm, frmAruteluOtsing, frmAruteluResult,
frmAlaealineSisestamine, frmAlaealineOtsi);
TRefForm = class of TForm; //замени на свой базовый клас
Const FListForm: Array[UserForm] of TRefForm =
(TAruteluSisestamineForm, TAruteluEttevalmForm,TAruteluOtsingForm, TAruteluResultForm,
TAlaealineSisestamineForm, TAlaealineOtsiForm);
//TAruteluSisestamineForm - это нужный класс!
Создается это так:
function TUserData.ActiveForm(ID: UserForm): TForm;
begin
Item := ID;
try
if FUserForm[Item].Count = 0 then
FUserForm[Item].Referens := FListForm[Item].Create(Application);
AddRef;
ChangeForm;
Result := FUserForm[Item].Referens;
except
on E: Exception do Result := nil; //Remov!!!
end;
end;
Сейчас я бы это сделел через интерфейсы. :(
← →
Vuk (2004-01-19 17:24) [18]to Erik:
>Сейчас я бы это сделел через интерфейсы.
Зачем?
← →
alex_*** (2004-01-19 17:30) [19][17] - все равно придется указывать от какого объекта получать интерфейс. К тому же у меня практически абстрактный базовый класс.
У меня классы от TObject наследуются. Проще будет от TPersistent отнаследовать, видимо.
← →
Vuk (2004-01-19 17:43) [20]to alex_***:
>все равно придется указывать от какого объекта получать
>интерфейс.
Либо организовывать что-то типа фабрик класса в COM. Но дело в том, что за счет ссылок на класс в Delphi любой класс сам же себе и фабрика.
← →
alex_*** (2004-01-19 17:49) [21]интересно как это работает...
что из себя представляет ссылка на класс...
← →
Vuk (2004-01-19 17:58) [22]Я же уже писал. Ссылка на класс - указатель на информацию о классе, которую генерирует компилятор. В общем случае ссылку на класс можно рассматривать как указатель на VMT.
← →
alex_*** (2004-01-19 18:01) [23]VMT это уже ближе к телу..
а то
>казатель на данные класса, которые генерирует компилятор.
как-то абстрактно и непонятно.
← →
Vuk (2004-01-19 18:04) [24]to alex_***:
>как-то абстрактно и непонятно.
Ну, вообще говоря, VMT - это только часть информации, до которой можно добраться через ссылку на класс.
← →
ЮЮ (2004-01-20 03:55) [25]>У меня классы от TObject наследуются. Проще будет от TPersistent отнаследовать, видимо.
А почему не так:
TMyClass = class of TMyAbstractObject;
TMyAbstractObject = class(TObject)
...
contructor Create(набор параметров, одинаковый для всех наследников);
end;
TMyObject1 = class(TMyAbstractObject)
...
end;
TMyObject11 = class(TMyObject1)
...
end;
TMyObject2 = class(TMyAbstractObject)
...
end;
использование:
FNewObject: TMyAbstractObject;
FNewObjectClass: TMyClass;
...
FNewObjectClass := TMyObject11; // класс любого наследника TMyAbstractObject
FNewObject := FNewObjectClass.Create(параметры)
← →
icWasya (2004-01-20 09:30) [26]только не забыть
TMyAbstractObject = class(TObject)
...
contructor Create(набор параметров, одинаковый для всех наследников); Virtual;
и
TMyObject11 = class(TMyObject1)
...
contructor Create(набор параметров, одинаковый для всех наследников); Override;
end;
← →
alex_*** (2004-01-20 14:57) [27]Наконец руки дошли переделать. Все работает.
Спасибо всем. то что нужно. Раньше я тип Class-reference старался не использовать по незнанию. Очень напрасно, как выяснилось.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.009 c