Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.01 c
3-2044
Владий
2004-01-05 16:43
2004.02.02
Как 3 запроса с одинаковой структурой совместить в 1


4-2426
Phantom
2003-11-24 19:57
2004.02.02
Как работать с функцией WinAPI - IsHungThread ?


1-2081
Maksss
2004-01-18 00:34
2004.02.02
#0


1-2185
Zheks
2004-01-21 11:09
2004.02.02
округление вверх с количеством знаков после запятой


9-1943
RIMMER
2003-07-17 23:32
2004.02.02
DelphiX: DXDraw на полный экран и обратно в runtime





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский