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

Вниз

Какой тип имеет указатель на конструктор 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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.018 c
3-2025
Mery
2004-01-06 11:17
2004.02.02
Автоподстановка


3-1971
Veetoyk
2004-01-10 13:07
2004.02.02
Объясните пожалуйста, ......


1-2122
Evgeniy_K
2004-01-18 11:18
2004.02.02
алгоритм масштабирования одного отрезка в другой


6-2259
h0use
2003-11-25 17:14
2004.02.02
Как реализовать чтоб сервре и клиент слушали порт?


3-1972
Петр
2004-01-09 10:13
2004.02.02
Ошибка с ADOQuery