|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Передача типа как параметр
Всем доброго времени суток! Понадобилась помощь. Все перерыл, не знаю как передавать тип, как параметр, как это делает к примеру функция SizeOf. Мы в параметр фенкции передаем тип например Integer, а она в свою очередь возврашает нам размер типа. Я хочу также передавать тип как параметр, а еще использовать переменные типа тип. Чтобы вопрос был понятен вот пример, как я хотел бы чтобы выглядел мой код:
Код:
Var VarType: AnyType; ... Procedure MyProc(MyType: AnyType); Var Buff: Pointer; begin ... GetMem(Buff, SizeOf(MyType)); ... FreeMem(Buff); ... end; ... begin MyProc(Integer); end. Заранее благодарен за помощь! Последний раз редактировалось Sahan911, 26.02.2012 в 21:11. |
#2
|
||||
|
||||
Насколько я знаю, SizeOf - не функция, а "магический" макрос. Проще передавать количество байт, занимаемых типом для приведенного выше кода.
jmp $ ; Happy End! The Cake Is A Lie. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
Sahan911 (26.02.2012)
|
#3
|
|||
|
|||
Re: Передача типа как параметр
Ну Макрос - это таже самая функция, только она описана где - то в Dll. Впринципе для данной ситуации можно передавать количество байт, но это не совсем то что мне нужно. Это лишь был пример как я могу использовать этот параметр. А если я захочу вот такую ситуацию сделать?:
Код:
Procedure MyProc(Param: AnyType); Var MyVar: AnyType; Ptr: Pointer; Int: Integer; begin ... GetMem(Ptr, SizeOf(Param)); ... MyVar := FuncЧтоЗаТип(Int); Int := MyVar(Ptr^); end; Т. Е. я хочу иметь переменую типа ТИП, или что - либо в этом духе, например чтобы определить размер с помощью функции SizeOf или для типизации разыменованного нетипизированного указателя. Если это возможно, то я еще хочу знать есть ли такая функция (FuncЧтоЗаТип), которая возвращает тип переменной. Если это не возможно есть ли методы , благодаря которым можно реализовать нечто подобное? Еще раз заранее спасибо. Код:
ShowMessage('HelloWorld!'); |
#4
|
||||
|
||||
У вас в корне не верное представление о макросе. Макрос - это значит, что код записывается на его месте. Никаких вызовов функции там нет. То есть на месте SizeOf(Integer) подставится 4 еще при компиляции. DLL тут ни при чем.
А вот описанная задача решается далеко не просто. Любые компиляторы, позволяющие использовать такое (например, технология шаблонов в C++) делают несколько вариантов функции для каждого случая. Опишу подробнее. Когда вы пишете Код:
procedure a123(...); var a:AnyType; Код:
sub esp, 4 ; Вычитаем из текущего адреса в стеке 4 байта. Теперь есть "зарезервированное" место, ; которое можно использовать для своих нужд; к нему никто не обратится. А если там неизвестный тип, то что ему вычитать? 1, 2, 4, 8, 10000? Это еще решаемо, но: а как потом с ним работать? Для сложения двух байт будет один код, а для двух строк - совершенно другой, ни капли не похожий. Примерно так: Код:
; сложить байтовые переменные a и b, aka a:=a+b mov al, [b] ; значение одного байта add [a], al ; прибавить к другому байту ; сложить строки aka Str1:=Str1+Str2 mov eax, [Str2] push eax ; адрес второй строки mov eax, [Str1] push eax ; адрес первой строки push eax ; адрес результирующей строки call StrAdd ; довольно длинная функция, дописывающая одну строку в конец другой. Делфи же является компилируемым языком, т.е. работающем непосредственно на железе. В скриптовых такая задача решается довольно просто: интерпретатор (программа, выполняющая код скрипта) может содержать в себе код работы с любыми типами, перед сложением проверить, какого типа переменные, и выбрать соответствующую функцию сложения. В компилируемых языках такая задача частично решается при помощи ООП и перегрузки операторов, однако это совсем другая история (и, кстати, достаточно медленная: если для сложения двух байт вызывать функцию - будут потери производительности раз в 5-10). Реализовать "нечто подобное" можно, например так: в функцию передаем ID типа (придумываем его сами: Byte-1, Word-2, Integer-3,...) и выбираем код в зависимости от переданного параметра обычным If или Case. Хотя честно говоря, уж не знаю, зачем такое может понадобится. Мне такое не нужно было ни разу в жизни. Вполне возможно, что есть более простые и быстрые решения вашей задачи. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 26.02.2012 в 21:55. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
Sahan911 (26.02.2012)
|
#5
|
|||
|
|||
Вообще, данная задача решается либо через generics/templates (если не ошибаюсь, то начиная с Delphi 2010 или XE они уже есть), либо через классы. Фактисески, тебе надо описать некоторый класс, имеющий некоторое стандартное поведение. Тогда любой другой твой тип будет наследником этого класса со всеми вытекающими...
Например, есть у нас базовый класс и функция, его использующая: Код:
type TMyTypeBaseClass = class private FMem : Pointer; public procedure ClassGetMem; virtual; abstract; procedure ClassFreeMem; virtual; abstract; procedure DoWork; virtual; abstract; property ClassMem : Pointer read FMem; end; procedure MyProc(MyVar : TMyTypeBaseClass); begin MyVar.ClassGetMem; MuVar.DoWork; MyVar.ClassFreeMem; end; Теперь можно создавать наследников этого класса и передавать из в эту процедуру. PS. На самом деле, когда ты используешь темплейты или дженерики, то компилятор в момент компиляции просто инстанциирует данный шаблон для переданного типа. Т.е. если у нас есть: Код:
var L1 : TList<Integer>; L2 : TList<String>; (не помню как там дженерики пишутся, т.к. пользуюсь пока Delphi 7, где их нет), то в скомпилированном коде по факту будет 2 экземпляра класса TList - один для целых и один для строк. Причем будет и 2 экземпляра кода. И это не только в Дельфи, в C++ и C# тоже самое происходит (в Java не уверен, т.к. эта штука может классы создавать на лету, бо как работает на виртуальной машине). Последний раз редактировалось lmikle, 26.02.2012 в 23:19. |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Sahan911 (26.02.2012)
|
#6
|
|||
|
|||
lmikle, Все верно, но мне нужно передавать не объекты, как параметр, а тип как параметр. Или например создать переменную типа ТИП. т.е.
Код:
Var MyType: AnyType; ... begin MyType:= integer; ... MyType := String; //и т.д. и т.п. Объекты передавать легко, а определять тип я не знаю как. Скорее всего это невозможно или очень сложно, но я всеже надеюсь получить ответ. Код:
ShowMessage('HelloWorld!'); |
#7
|
||||
|
||||
Как можно передать тип, если тип - это понятие, существующее только на этапе компиляции программы? Это просто несколько букв, в зависимости от которых комиплятор ведёт себя по-разному. После компиляции никаких типов не существует, существуют байты и их количество.
jmp $ ; Happy End! The Cake Is A Lie. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
Sahan911 (27.02.2012)
|
#8
|
|||
|
|||
Ну, тут можно посмотреть в сторону метаклассов. Экземпляр метакласса собственно и есть класс, т.е. тип. Но все-равно не понимаю зачем оно тебе. Я тебе дал пример нормального решения для твоей задачи. Более того, это даже можно использовать из bpl-ей (из dll нельзя, т.к. там TObject'ы будут разные, но можно и попробовать - если не надо проверять тип, а пользоваться только интерфейсом класса, то должно прокатить).
А вообще, что тебе мешает использовать вариант (Variant). Посмотри функции работы с вариантами... там ест и получение типа варианта. |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Sahan911 (27.02.2012)
|
#9
|
|||
|
|||
Сорри , (конечно с этого надо было начинатть) я забыл сказать, что данную задачу я решаю сейчас не в Delphi а в ABC Pascal . Там немного все по - другому и нет типа Variant(я с ним в Delphi работал).
Код:
ShowMessage('HelloWorld!'); |
#10
|
|||
|
|||
PHP код:
PHP код:
PHP код:
PHP код:
военная тайна что-ли? зачем это передавать то? что это должно дать? и что из этого не дают объекты? |