Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "KOL";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];

Вниз

Недомолвка в FAQ насчет AncestorOfObject   Найти похожие ветки 

 
BenGun   (2006-03-06 18:55) [0]

>> В KOL нет RTTI, поскольку используется "старая" ООП-модуль (не class, а object). В итоге вместо
>> MySuper as TSmth пишем PSmth(MySuper), а вместо MySuper is TSmth пишем TSmth.AncestorOfObject(MySuper)

разве не стоит указать, что AncestorOfObject возможно использовать только в методах объекта, являющегося потомком TSmith или самого TSmith?


 
Thaddy   (2006-03-06 19:43) [1]

Yup, this code is verifying, not falsifying (i.e: it does not test for impossible options, it verifies the code is valid. Scientific  mistake :-)) Read Karl Popper about it.


 
Vladimir Kladov   (2006-03-06 19:52) [2]

А он вообще работает? А то он долго не пахал, потом кто-то фиксил, а мне он как-то не был нужен, я и не смотрел, работает ли он вообще.


 
Thaddy   (2006-03-06 20:35) [3]

Yes, but you know that generally is not good enough:
and obviously, the value of AncestorOfObject is undefined, not nil! when it fails.
Therefore, it isn"t very good code (although generally it works ;) ) It might have been in the late 10th and early 20th century. :)


 
BenGun   (2006-03-07 16:16) [4]

to Vladimir Kladov
работает в указанной области видимости (еще кое где, но там глючит)

to Thaddy
I always can do before call AncestorOfObject to check for nil and it"s not a problem:)

Мужики, дело такое... В ООП да не иметь возможности проверить экземпляр объекта на принадлежность к типу - это даже не смешно, это катастрофа! нет, это просто кошмар! :( Насчет "мне он как-то не был нужен" я смею сомневаться в искренности.

P.S.
KOL - очень добротный проект, и мне хотелось бы его использовать, но без вышеупомянутой проверки это нереально, ибо
1. Привык
2. Это очень удобный механизм и неотемлемая часть ООП! Какого лешего?!  

Огромное спасибо за участие (если честно, то не надеялся)

ICQ 111326219(hidden/always offline for "not in contacts")
email bgun@list.ru


 
ECM ©   (2006-03-07 17:14) [5]


> не иметь возможности проверить экземпляр объекта на принадлежность
> к типу - это даже не смешно, это катастрофа! нет, это просто
> кошмар

Между прочим в КОЛ 99% контролов это TControl. И "вообще поменьше типов" - один из постулатов КОЛ. И "какого лешего"? :))
Если это Ваши типы - никто не мешает сделать свой механизм.. Если нет сил (умения ) сделать  свой - посмотрите что не так в том что есть... Это не так уж сложно. (Важно то что это нужно именно Вам)
Но учтите - разницу между ComboBox-ом и ListBox-ом например (да и всеми остальными "стандартными" контролами ) - Вы не обнаружите - это всё TControl


 
BenGun   (2006-03-07 17:42) [6]

to ECM
Уважаемый, безусловно меня в первую очередь интересует построение собственных классов и дальнейшее их использование(!!!). Паскаль можно задействовать не только для построения гуёв: для меня важнен комплекс - и гуй, и математика. Насчет Вашего "свой механизм" - я вижу только вариант, при котором мне надо будет создавать экземпляр объекта проверяемого типа.
>> "если нет сил (умения ) сделать  свой - посмотрите что не так в том что есть... Это не так уж сложно" Не могли бы Вы поконкретнее? Очень похоже на флейм типа "ДА ТЫ НЕ НА ТОМ ЯЗЫКЕ ПИШЕШЬ!!"

С TControl"ами сейчас проверю (хотя это частная задача, имеющая отношение к проблемме весьма второстепенное)


 
ECM ©   (2006-03-07 18:07) [7]


> Не могли бы Вы поконкретнее?

Конкретнее не бывает (см. KOL.PAS):

class function TObj.AncestorOfObject(Obj: Pointer): Boolean;
asm
       MOV     ECX, [EAX]
       MOV     EAX, EDX
       JMP     @@loop1
@@loop:
       MOV     EAX,[EAX]
@@loop1:
       TEST    EAX,EAX
       JE      @@exit
       CMP     EAX,ECX
       JNE     @@loop
@@success:
       MOV     AL,1
@@exit:
end;

Смотрим, запускаем для разных классов, изучаем в отладчике... Или это надо сделать мне? :))


> С TControl"ами сейчас проверю


Это - туда же (см. KOL.PAS) :)))

З.Ы.  Флейм про "лешего с гуЁм" - продолжать не стоит - не надо :))
(Вот, не хотел же отвечать на ... )


 
BenGun   (2006-03-07 18:32) [8]

Увы, ассемблер для меня - черный ящик. В Kol.pas смотрю прямо сейчас (снимаю шляпу перед автором, объем работы проделан чудовищный). Вижу, что все PControl есть именно PControl и тут, видимо, подразумевается иной механизм (скорее всего сравнение с каким-нибудь classname).

И всё-таки хотелось бы услышать чего-нибудь по существу вопроса :)
Вопрос стоит: "Как же быть?" :)


 
BenGun   (2006-03-07 18:42) [9]

для конкретики: бог с ними, с control"ами, что насчет наследников TObj?


 
BenGun   (2006-03-07 18:51) [10]

даже так, еще конкретнее. Как мне развести следующее:
имеются типы
TAA->TA->TObj
TAB->TA->TObj
задача:

program
(...)
var
 A: PA;
begin
 A := NewXXX; (вирианты A, AA, AB)
 if (проверка A is TA) then
   Do1
 else
 if (проверка A is TAA) then
   Do2
 else
 if (проверка A is TAB) then
   Do3;
end;


 
BenGun   (2006-03-07 18:56) [11]

хехе. ща бы меня тут волхвы похоронили :))) Оговорюсь и поправлю код (если успел)

program
(...)
var
A: PA;
begin
A := NewXXX; (вирианты A, AA, AB)
if (проверка A is TA) then
begin
  if (проверка A is TAA) then
    Do2
  else
  if (проверка A is TAB) then
    Do3;
 end;
end;


 
z007   (2006-03-07 21:20) [12]

Проблема знакомая. Сам с ней столкнулся при написании компонентов (http://delphimaster.net/view/11-1140304918/).

Однако:
Если это есть самопальные типы, ну сделай в них поле / property
(ftypeID:byte|word<as 2Chars>|integer<as 4 Chars>|string, наконец). Как правило, без проверки типов действительно можно обойтись, в т.ч при создании собственных компонентов. Надо только врубиться в "правила KOL".


 
BenGun   (2006-03-09 08:05) [13]

:) это-то понятно. Если уж на то пошло, можно обойтись и процедурным программированием (даже блочным копированием! процедуры - буржуазная роскошь!) Речь идет о трудоёмкости. Вообще говоря, я хотел высказать пожелание подправить FAQ (втайне надеясь, что я чего-то недопонял и механизм существует). Спасибо всем, принявшим участие и авторам KOL особенно. Повторюсь: труд потрясает масштабами(!!!) и не юзать ТАКОЕ - просто преступление перед человечеством :)))))


 
Barloggg   (2006-03-09 09:21) [14]

хм... все свои классы я делаю именно class"ами. никто не запрещает. да и стоит это не дорого. где-то 3-5 кб ехе-шника.
А KOL использую только для компактных окошек и контролов.
А там где мне не нужно многократное наследование или я точно знаю какой где тип то тогда использую TObj.

еще из первых уроков которые я прочел прежде чем решиться вообще скачивать и ставить себе KOL+MCK мне стало ясно, что вся мощь class тут не используется и рассчитывать на 100% альтернативу бесполезно.

мне кстати недавно понадобилось свалить в одну кучу с пяток наследников от TObj разных типов... и я сбацал "оглавление" с жестко размеченными индексами для каждого объекта которое представляет собой динамический массив of PObj.

помню как-то сбацал "главного предка" который был простым наследником с одним единственным дополнительным полем - именем текущего класса. и в конструкторе идет заполнение этого поля текущим именем... а все остальные классы наследовал от него...


 
ECM ©   (2006-03-09 13:01) [15]

Я вижу ясности в главном вопросе об AncestorOfObject, так и не прибавилось... Поэтому приведу тут свои соображения (решил посидеть пару часов - разобраться что к чему) - если я где-то ошибаюсь - пожалуйста поправьте. Вообще-то я считал, что в таких базовых вопросах
уже давно всё в порядке (сам я этой функцией не пользуюсь) - ну да ладно
смотрим (у меня D6 и KOL 2.34):

class function TObj.AncestorOfObject(Obj: Pointer): Boolean;
asm
      MOV     ECX, [EAX]  
// EAX на входе функции равен Self и следовательно в ECX попадает первый
// DWORD из памяти распределенной под объект. А как можно увидеть из
// ассемблерного кода функции TypeOf там лежит указатель на VMT TObj
// Эксперимент с вызовом функции напрямую (без создания
// экземпляра класса) показывает что в EAX передается указатель на некую
// ячейку памяти в которой тоже расположен указатель на VMT TObj
// Итого: ECX => VMT TObj
      MOV     EAX, EDX
// EAX => указатель на проверяемую переменную
      JMP     @@loop1
@@loop:
      MOV     EAX,[EAX]
//
@@loop1:
      TEST    EAX,EAX
//Проверка на ноль
      JE      @@exit
      CMP     EAX,ECX
// В первом же цикле сравнивается указатель на VMT с указателем на
// переменную!!!! (Предполагалось я думаю сравнивать указатели на VMT)
// Если бы во второй команде функции было MOV EAX,[EDX] то в первом
// цикле так бы и случилось....но да ладно потом выполняется
// MOV EAX,[EAX] и в EAX уже VMT проверяемого объекта - если это
// VMT TObj то во втором цикле проверки - всё закончится, а если нет?
// см. ниже

      JNE     @@loop
@@success:
      MOV     AL,1
@@exit:
end;


Если во втором цикле проверка не проходит - в EAX загружается новое значение - теперь оно берется ПРЯМО ИЗ VMT!  Т.к. далее сравниваться оно будет с VMT Tobj - остается предположить что в первой ячейке VMT автор функции ждет найти указатель на родительскую (?) VMT... и тогда цикл будет продолжен до совпадения либо до корневого класса где указатель на родительскую VMT = 0 ... ?.... Что то я не припомню, чтобы VMT для старой объектной модели были указатели на предков. Ну да это несложно проверить. Создаем в программе такие классы (например как в [10]):

type

 PA = ^TA;
 TA = object (TObj)
 destructor Destroy; virtual;
 end;

 PAA = ^TAA;
 TAA = object(TA)
 end;

 PAB = ^TAB;
 TAB = object(TA)
 end;

 PTT = ^TT;
 TT = class
   destructor Destroy; virtual;
 end;


После тщательного изучения кода получилась следующая картина - компилятор сгенерировал 4-е VMT расположенные в начале сегмента модуля. Я изучил их структуру и вот что у меня получилось(дамп пямяти):

Address | Value     | Desc
--------+-----------+------------------------------------
$406F2C | $00406F38 | (vmtSelfPtr     ) | VMT
$406F30 | $00000018 | (vmtInstanceSize) | TA = object(TObj)
$406F34 | $00000000 | (vmtPtrOffs     ) |
$406F38 | $00403EF0 | _TObj.Init        |
$406F3C | $004074D4 | TA.Destroy        |
--------+-----------+------------------------------------
$406F40 | $00406F4C | (vmtSelfPtr     ) | VMT
$406F44 | $00000018 | (vmtInstanceSize) | TAA = object(TA)
$406F48 | $00000000 | (vmtPtrOffs     ) |
$406F4C | $00403EF0 | _TObj.Init        |
$406F50 | $004074D4 | TA.Destroy        |
--------+-----------+------------------------------------
$406F54 | $00406F60 | (vmtSelfPtr     ) | VMT
$406F58 | $00000018 | (vmtInstanceSize) | TAB = object(TA)
$406F5C | $00000000 | (vmtPtrOffs     ) |
$406F60 | $00403EF0 | _TObj.Init        |
$406F64 | $004074D4 | TA.Destroy        |
--------+-----------+------------------------------------
$406F68 | $00406FB4 | (vmtSelfPtr     ) | VMT
$406F6C | $00000000 | (vmtIntfTable   ) | TT = class
$406F70 | $00000000 | (vmtAutoTable   ) |
$406F74 | $00000000 | (vmtInitTable   ) |
$406F78 | $00000000 | (vmtTypeInfo    ) |
$406F7C | $00000000 | (vmtFieldTable  ) |
$406F80 | $00000000 | (vmtMethodTable ) |
$406F84 | $00000000 | (vmtDinamicTable) |
$406F88 | $00406FB8 | (vmtClassName   ) |
$406F8C | $00000004 | (vmtInstanceSize) |
$406F90 | $00401000 | (vmtParent) VMT TObject
$406F94 | $004028B0 | TObject.SafeCallException
$406F98 | $004028BC | TObject.AfterConstruction
$406F9C | $004028C0 | TObject.BeforeDestruction
$406FA0 | $004028C4 | TObject.Dispath
$406FA4 | $004028B8 | TObject.DefaultHandler
$406FA8 | $00402794 | TObject.NewInstance
$406FAC | $004027B0 | TObject.FreeInstance
$406FB0 | $004027EC | TObject.Destroy
$406FB4 | $004074EC | TT.Destroy
$406FB8 | $90545402 | #90"TT"#02 (ClassName)


vmtSelfPtr (VMT - 12) - указатель на собственно VMT. Delphi резервирует (и как бы скрывает от программиста) первые служебные ячейки VMT. Значение как
можно заметить - указывает на начало собственно таблицы виртуальных
метедов (т.е. на первый виртуальный метод). Имеено значение передается
записывается в первую ячейку памяти выделенной под объект.
vmtInstanceSize (VMT - 8) - размер памяти который необходимо выделить для размещения объекта. Равен сумме размеров полей объекта + 4 (для хранения указателя на VMT). Именно это значение возвращается по SizeOf для объекта.
vmtPtrOffs (VMT - 4) . Смещение в памяти выделенной под объект, где лежит указатель на VMT.(Это видно при анализе System.ObjSetup) Как видно это значение всегда (?) нулевое. Т.е. указатель на VMT всегда (?) расположен в первой ячейке памяти объекта (т.е. первое и неявное поле типа Pointer)

Как видно  в VMT для объектной модели - нет никаких признаков наличия
указателя на VMT предка. И следовательно определить способом предлагаемым в AncestorOfObject кто есть предок просто невозможно!
Да и честно говоря - способа это сделать я не вижу. Сравнение кода System.pas для других версий Delphi показывает что структура VMT для
старой объектной модели везде (незнаю только что в D2, но скорее всего и там тоже) одинакова.....:(
...Да и еще - использование этой функции в конце-концов может привести к AV. Т.к на третьем этапе в AX попадает указатель на первый VM объекта,
на четвертом - строится указатель из первых 4 байт кода первого VM и дальше катится неконтроллируемо (хорошо если по пути случайно попадется нулевая ячейка) - и (как было в моем случае) падает с AV.

Может эта функция была написана для FPC и там в VMT есть указатели на VMT предка - не знаю...
Если есть кто из авторов этой функции ? Может кто пояснит ситуацию?

З.Ы.  Кстати из дампа VMT для TT видно, что объявления
 TT = class
...
 end;

 TT = class(TObject)
...
 end;

это действительно одно и тоже ... :))


 
ECM ©   (2006-03-09 18:23) [16]


> z007   (07.03.06 21:20) [12]


> Если это есть самопальные типы, ну сделай в них поле / property



> Barloggg   (09.03.06 09:21) [14]


> помню как-то сбацал "главного предка" который был простым
> наследником с одним единственным дополнительным полем



> BenGun   (07.03.06 18:42) [9]
> для конкретики: бог с ними, с control"ами, что насчет наследников
> TObj?


Кстати, для этих целей вполне можно использовать поле TObj.Tag. В конструкторе потомка заносить туда "уникальный" номер (для TObj это будет 0). Потом анализировать ...


 
GMax   (2006-03-09 23:48) [17]

а ещё можно USE_NAMES и давать осмысленные имена :)


 
ECM ©   (2006-03-10 09:27) [18]


> GMax   (09.03.06 23:48) [17]

Согласен, но это уже конкретизация экземпляра класса(объекта), а речь выше шла о идентификации класса объекта (типа) - поэтому в случае осмысленных имен - придется делать их парсинг, что, вобщем,является более "дорогостоящей" операцией, чем сравнение двух целых чисел
:))



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

Форум: "KOL";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.097 c
6-1153678565
Vitaliy
2006-07-23 22:16
2006.12.24
Сокеты, таймаут


1-1162825345
dima123
2006-11-06 18:02
2006.12.24
Хинт


15-1164959291
вразлет
2006-12-01 10:48
2006.12.24
Задача


15-1164922671
ЭРИКА
2006-12-01 00:37
2006.12.24
С ДНЕМ РОЖДЕНИЯ!


15-1164735877
sniknik
2006-11-28 20:44
2006.12.24
Проблема(?) с µTorrent-ом? Нет текста в настройках и др. окнах.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский