主页
Top.Mail.Ru Yandeks.Metrika
论坛:“主要”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

向下

定义构造函数地址 找到类似的分支


Ученик   (2002-07-16 16:13) [0]

Можно по адресу класса определить адрес конструктора объектов этого класса ?

VAR
P:指针;
开始
P := TBitmap;

Необходимо вычислить адрес TBitmap.Create, используя P, возможно ли ?



Skier   (2002-07-16 16:20) [1]

>学生
为什么呢?
Что хочешь сделать ??



Ученик   (2002-07-16 16:23) [2]

>滑雪者
Вызывать по адресу класса создание объектов этого класса, с компонентами все понятно, там constructor; override;, а вот если от TPersistent или TObject ????



Skier   (2002-07-16 16:27) [3]

>学生
для TPersistent копай :
- RegisterClass
- UnRegisterClass
- RegisterClasses
- UnRegisterClasses
- FindClass
- GetClass






Ученик   (2002-07-16 16:29) [4]

Вызывается конструктор TObject



Skier   (2002-07-16 16:30) [5]

>学生
在dogonku:
Почитай про метаклассы.



Skier   (2002-07-16 16:32) [6]

>学生
А почему TObject у тебя же TBitmap ?



Digitman   (2002-07-16 16:38) [7]

ну, к примеру :

showmessage(inttohex(integer(@ TBitmap.Create), 8));

А если метод-конструктор с интересующим тебя именем объявлен как overload ? Что тогда ?

И - зачем это тебе ? Если не секрет ?




Ученик   (2002-07-16 16:41) [8]

>滑雪者
VAR
P : TPersistentClass;
开始
RegisterClasses([TBitmap]);
P := GetClass("TBitmap");
if P <> nil then
P.Create;
Вызывается TObject.Create

>数字人
Вызывать по адресу класса создание объектов этого класса.



Digitman   (2002-07-16 16:42) [9]

Ну, предположим, вызовешь ты конструирующий метод класса ..
А экземпляр-то собственно кто будет за тебя создавать ?



Skier   (2002-07-16 16:48) [10]

>学生


type
TBitmapClass = class of TBitmap;

var
P : TBitmapClass;
begin
RegisterClasses([TBitmap]);
P := TBitmapClass(GetClass("TBitmap"));
if P <> nil then P.Create;



Ученик   (2002-07-16 16:53) [11]

>数字人
Экземпляр то создается, и P.Create.Free вызовет TBitmap.Destroy, только вот конструктор вызвать проблема.



Ученик   (2002-07-16 16:56) [12]

>数字人
Экземпляр то создается, и P.Create.Free вызовет TBitmap.Destroy, только вот конструктор вызвать проблема.
>滑雪者
TBitmap взят для примера, на его месте может быть любой другой.

Есть какая-то таблица методов, конструкторы там не постоянном месте ?



Digitman   (2002-07-16 17:39) [13]

>学生

Нет, подожди ...
кем/чем и как будет создаваться экземпляр у тебя, коль ты не хочешь отказаться от услуг компилятора ?

тело метода-конструктора этим не занимается, его задача - инициализация уже существующего экземпляра



Ученик   (2002-07-16 17:46) [14]

>数字人
Я не знаю ответа, я еще только учусь, просто попробуйте выполнить код который указан выше, объекты создаются,
не вызывается конструктор определенный именно для них



Skier   (2002-07-16 17:55) [15]

>学生
К сожалению, у потомков TPersistent конструктор не
перекроешь (override).
Это можно делать только начиная с TComponent :(



Digitman   (2002-07-16 17:56) [16]

>学生

Конечно , объект будет создаваться в этом примере ! В этом и сомнений нет )

Но ведь в этом примере работу по внедрению и вызову кода создания экземпляра неявно выполняет за тебя компилятор ...

Ты же хочешь вызвать некий метод-конструктор в run-time просто как некую процедуру инициализации экземпляра. Вопрос - какого экземпляра ? Об этом придется заботиться самостоятельно ...

Еще один вопрос - а как ты надеешься вызывать метод-конструктор, даже зная его адрес, если он имеет один или более (заранее неизвестно) параметров ?




Ученик   (2002-07-16 18:16) [17]

>数字人
>Ты же хочешь вызвать некий метод-конструктор в run-time просто >как некую процедуру инициализации экземпляра.

Я хочу вызвать конструктор объекта, по-моему он должен делать все, по-крайней мере кроме вызова TObject.Create там больше ничего нет. С несколькими параметрами действительно беда, но на это хотелось пока закрыть глаза, хотя какие-то странные сообщения мелькают в Delphi, если библиотеки компонентов не соответствуют друг другу.



Юрий Зотов   (2002-07-16 18:25) [18]

>学生

Что-то все у Вас запутано как-то. Объясните просто - что нужно сделать? Создать некомпонентский объект, зная ссылку на его класс? Или что-то другое?

А Ваш пример

类型
TBitmapClass = class of TBitmap;

VAR
P : TBitmapClass;
开始
RegisterClasses([TBitmap]);
P := TBitmapClass(GetClass("TBitmap"));
if P <> nil then P.Create;

полностью эквивалентен самому обычному вызову TBitmap.Create. Зачем такие навороты?



Ученик   (2002-07-16 18:29) [19]

> Yuri Zotov
Вы чего-то напутали, это не мое.



Skier   (2002-07-16 18:31) [20]

Это моё. Просто я-то думал что Ученик хочет иметь
дело с наследниками TBitmap-а.
Он что-то другое задумал:)



[NIKEL]   (2002-07-16 18:36) [21]

по моему адреса деструктора и конструктора получить невозможно...



Skier   (2002-07-16 18:39) [22]

> [NIKEL]
showmessage(inttohex(integer(@TBitmap.Create), 8));

Чем тебе не адрес ? :)



Юрий Зотов   (2002-07-16 18:48) [23]

Действительно напутал, приношу свои извинения.

Н в чем же, все-таки вопрос? Понимаете, я не зря спрашиваю. Я уточняю потому, что примерно догадываюсь, что Вы хотите и знаю, как это делается. Но чтобы говорить, нужно не догадываться, а быть полностью уверенным.



Ученик   (2002-07-16 19:11) [24]

> Yuri Zotov
Так тут нет никаких подводный камней, хочется по адресу класса создать объект этого класса.



vuk   (2002-07-16 19:18) [25]

到Digitman:
>тело метода-конструктора этим не занимается, его задача -
>инициализация уже существующего экземпляра
....
>Ты же хочешь вызвать некий метод-конструктор в run-time просто
>как некую процедуру инициализации экземпляра. Вопрос - какого
>экземпляра ? Об этом придется заботиться самостоятельно ...

Здесь Вы не правы. Созданием экземпляра занимается именно конструктор. И получить его адрес можно, и вызвать тоже можно (если знать как). Только вот единственное - лучше этого не делать. :o)



vuk   (2002-07-16 19:25) [26]

给学生:
Экземпляр создать можно, но не всегда можно это сделать корректно. Например для наследников TComponent это делается просто (там имеется виртуальный конструктор), а вот для других классов это может быть проблематичным.



Ученик   (2002-07-16 19:27) [27]

> vuk
С другими как раз и вопрос )))



vuk   (2002-07-16 19:32) [28]

Если Вам нужно создавать экземпляр _любого_ класса, то такая задача в общем виде не решается, поскольку у каждого класса свой конструктор и он ни в каких таблицах не прописан.



Ученик   (2002-07-16 19:36) [29]

> vuk
>...ни в каких таблицах не прописан.

遗憾



Digitman   (2002-07-17 10:02) [30]

> vuk

Здесь есть вот какие тонкости :

Если перед вызовом конструирующего метода некоего класса РОН dl = 1, то непосредственно перед инициализацией экземпляра будет вызвана системная процедура ClassCreate, отвечающая за генерацию экземпляра. В противном случае (РОН dl = 0) будет произведена только попытка инициализации, и это приведет к исключению при отсутствии экземпляра.

Все inherited-конструкторы вызываются с dl = 0.

Вызов любого конструирующего метода любого класса всегда предваряется занесением в РОН eax адреса VMT

Кр.того, если конструирующий метод класса имеет параметры, их также нужно передавать : первый параметр (в порядке их перечисления в декларации конструктора) - в РОН ecx, остальные - последовательным занесением в стек.

>学生

Всю эту последовательность действий формирует компилятор "прозрачно" для программера.

Незнание этих фактов при явном (по факт.вычисленному адресу) вызове конструктора обязательно приведет к исключительной ситуации.




Ученик   (2002-07-17 10:10) [31]

>数字人
Если что-то надо, можно и на встроенном ассемблере написать, только вот похоже адреса то нету, в любом случае, спасибо.



Игорь Шевченко   (2002-07-17 10:20) [32]

Адрес деструктора прописан в таблице VMT со смещением -4
(vmtDestroy)



Digitman   (2002-07-17 10:32) [33]

>学生

Как это - нет ? Вот же он !

procedure TfMain.ButtonXClick(Sender: TObject);
VAR
VAR
p: procedure;
c: TClass;
t: TObject;
开始
p:= @TComponent.Create;
c:= GetClass("TComponent");
ASM
mov dl,1 // создавать экземпляр
mov eax, [c] // VMT
mov ecx, 0 // Owner = nil
call dword ptr [p] // собственно - вызов конструктора по адресу
mov [t], eax // результат - ссылка на созданный и иниц-ный экз-р
结束;

t.free; // разрушение созданного объекта

结束;



Ученик   (2002-07-17 10:52) [34]

>伊戈尔舍甫琴科
Речь шла о конструкторе
>数字人
У нас проблема с вызовом конструкторов объектов порожденных от TObject и TPersistent, с компонентами проблем нет у них конструктор override; и все вызывается обычным образом
TComponentClass(FindClass("Имя класса")).Create(AOwner)



vuk   (2002-07-17 10:58) [35]

>Здесь есть вот какие тонкости
Я именно об этом. Вообще говоря, можно написать то, что написали Вы несколько проще. Если вспомнить, что конструктор - функция, возвращающая созданный экземпляр, то все просто. Конструктор без параметров можно представить примерно так:

类型
TSimpleConstructor = function (ClassRef : TClass) : TObject; register;
соответственно конструктор TComponent будет иметь вид

类型
TComponentConstructor = function (ClassRef : TClass; AOwner : TComponent ) : TObject; register;

Тогда вызов делается проще. Предположим, что в вышем примере переменная p имеет тип TComponentConstructor и содержит адрес конструктора, тогда его вызов будет примерно следующим:
ASM
mov dl, 1
结束;
t := P(c, nil);

Вот только в приведенном Вами примере все это будет лишним, поскольку все то же самое можно сделать проще, поскольку у наследников TComponent есть виртуальный конструктор и все действия, приведенные выше не особо нужны. Автору вопроса в решении его задачи это ни коим образом не поможет, поскольку он не знает, какого класса экземпляры он будет создавать и следовательно не будет иметь возможности получить адрес конкретного конструктора (у Вас это сделано явно в выделенной строке).
А с наследниками TComponent все просто. Предположим, что в переменной A содержится экземпляр какого-то наследника TComponent, тогда:
C := TComponentClass( A.GetClass ).Create( nil );




Digitman   (2002-07-17 11:16) [36]

> vuk
>>Автору вопроса в решении его задачи это ни коим образом не поможет

Разумеется, не поможет ! И я об этом говорю, только вот он никак это , видимо, не уразумеет.

А все то, что я , как ты говоришь, "сложно" изложил - лишь в стремлении именно наглядно показать, что адрес корректно определяется и явный вызов констр.метода по полученному адресу вполне возможен, но сопряжен с вышеописанными проблемами.

>学生

TComponent - прямой наследник TPersistent, и непонятно в таком случае, какие у тебя сложности, если ты говоришь, что конструируешь любого наследника TComponent без проблем.



Ученик   (2002-07-17 11:26) [37]

>数字人
>И я об этом говорю, только вот он никак это , видимо, не >уразумеет.

Я уже давно остановился Ученик (16.07.02 19:36)

>TComponent - прямой наследник TPersistent, и непонятно в таком >случае, какие у тебя сложности, если ты говоришь, что >конструируешь любого наследника TComponent без проблем.

Внимательности вам не хватает мастера (Digitman, Юрий Зотов), внимательности, а так цены бы вам не было ))), так много и хорошо пишете про простые вещи.







Digitman   (2002-07-17 11:56) [38]

>学生

Я вот не вижу, что ты "остановился" ...
Так ты до сих пор и не смог вразумительно объяснить суть проблемы...

Тебе ж сказали уже - в любом случае нужно заранее знать класс зарегистрированного объекта, иметь ссылку на дескриптор класса и иметь декларацию его конструктора . Только тогда с помощью VMT можно вызывать конструирующие методы класса с приведенными выше оговорками.



Ученик   (2002-07-17 12:03) [39]

>数字人
Внимательности, внимательности и еще раз внимательности, прочитайте еще раз эту страницу.



Digitman   (2002-07-17 12:40) [40]

>学生

Чушь. В данном случае именно ты невнимателен.

Цитирую тебя :

(1)
>>Необходимо вычислить адрес TBitmap.Create, используя P, >>возможно ли ?

(2)
>>Вызывается конструктор TObject


Вот - еще раз - код, отвечающий на твой вопрос (1) и опровергающий твое утверждение (2)

Тот самый твой TBitmap - не имеющий к TComponent отношения.


procedure TfMain.ButtonXClick(Sender: TObject);
var
var
p: procedure;
c: TClass;
t: TObject;
begin
p:= @TComponent.Create; // вот тебе адрес
RegisterClass(TBitmap);
c:= GetClass("TBitmap");
asm
mov dl,1
mov eax, [c]
call dword ptr [p] // вот тебе создание объекта TBitmap
mov [t], eax
end;

t.free; // вот тебе разрушение созданного объекта TBitmap

end;


Отрассируй и убедись сам !!!



Ученик   (2002-07-17 12:44) [41]

>数字人
Если Вам будет легче, то каюсь, я сам не знаю что хочу, задаю дурацкие вопросы и не прислушиваюсь к ответам великих мастеров Delphi, надеюсь мы не будем продолжать, кто-то должен оказаться умнее.



Digitman   (2002-07-17 12:48) [42]

>学生

Так вот если "сам не знаю что хочу" - разберись для начала, а потом уже упрекай стремящихся помочь тебе в невнимательности. С аргументами серьезными, а не словоблудием !



Ученик   (2002-07-17 12:52) [43]

>数字人
没有评论



Digitman   (2002-07-17 13:00) [44]

>学生
Да как тебе будет угодно, сударь)



Ученик   (2002-07-17 13:04) [45]

>数字人
)



Уролог   (2002-07-17 13:10) [46]

Господа ! Сдается мне, старому специалисту, что у Digitman © потолще и подлиннее, чем у Ученик. И есть подспудная мысль, что Ученик"а мучает юношеский максимализм. Но это уже к другому специалисту.



Ученик   (2002-07-17 13:22) [47]

>Уролог
Вы сейчас полностью дискредитировали уважаемого Digitman.



Skier   (2002-07-17 13:23) [48]

Ребята, завязывайте...



Digitman   (2002-07-17 14:32) [49]

>学生

За меня не волнуйся)
Мне совершенно по-барабану беспредметный треп постороннего.

Вот гораздо важнее, что ты скажешь по теме ...
Но ты-таки решил закрыть тему, не доведя ее до истины ... И совершенно напрасно ...



Страницы: 1 2 整个分支

论坛:“主要”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

楼上









内存:0.74 MB
时间:0.067 c
1-95274
AFROLOV
2002-07-15 13:18
2002.07.29
通过引用传递参数


1-95391
Ev_genus
2002-07-16 03:53
2002.07.29
类型的变量的大小。


3-95236
鳗鱼
2002-07-08 15:49
2002.07.29
如何确定是否包含TTR范围(SetRange)


14-95511
Mirkoorio
2002-07-01 18:39
2002.07.29
FAT32还是NTFS?


3-95195
ProfiUgl
2002-07-05 08:38
2002.07.29
提供有关选择普通DBLookUpCombo的建议....





南非荷兰语 阿尔巴尼亚人 阿拉伯语 亚美尼亚 阿塞拜疆 巴斯克 白俄罗斯 保加利亚语 加泰罗尼亚 简体中文 中国(繁体) 克罗地亚 捷克 丹麦语 荷兰人 英语 爱沙尼亚语 菲律宾人 芬兰 法文
加利亚西语 格鲁吉亚语 德语 希腊语 海地克里奥尔语 希伯来语 印地语 匈牙利 北日耳曼语 印度尼西亚人 爱尔兰语 意大利语 日本性玩偶 韩语 拉脱维亚 立陶宛 马其顿 马来语 马耳他语 挪威语
波斯语 波兰语 葡萄牙语 罗马尼亚 俄语 塞尔维亚 斯洛伐克 斯洛文尼亚 西班牙语 斯瓦希里 瑞典语 泰国人 土耳其 乌克兰 乌尔都语 越南人 威尔士语 意第绪语 孟加拉 波斯尼亚
宿务 世界语 古吉拉特语 豪萨语 苗族 伊博 爪哇 卡纳达语 高棉 老挝 拉丁语 毛利 马拉 蒙古人 尼泊尔 旁遮普 索马里 泰米尔人 泰卢固语 约鲁巴语
祖鲁
英文 Французский Немецкий Итальянский Португальский 俄文 Испанский