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

Вниз

Class Functions   Найти похожие ветки 

 
SPeller ©   (2004-07-06 07:12) [0]

Всем доброго времени суток.

Я вот что-то не могу понять чем отличаются функции, объявленные как class function FuncName () ? Буду очень благодарен за разъяснение что это такое и с чем его едят.


 
MBo ©   (2004-07-06 07:19) [1]

Хелп по Class methods.
Они работают не с экземпляром объекта, а с самим классом, так что не требуют создания объекта, но в них нельзя использовать поля и т.д. Пример - TObject.ClassName


 
SPeller ©   (2004-07-06 07:23) [2]

Это я тоже читал, что с классами работают. Вот только не могу понять, как это?

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


 
MBo ©   (2004-07-06 07:26) [3]

>обычный метод класса вызвать без создания объекта без проблем.
????

И что будет:

s:TStringList;
begin
s.add("a");


 
SPeller ©   (2004-07-06 07:36) [4]

А то что метод обращается к полям - это уже его проблема. Вызывается ведь. И в чем тогда отличие в запрете обращений к полям классовых функций и необходимости отсутствия обращений к полям класса простых методов чтобы небыло ошибки?

Вот живой пример:

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   function SomeFunc: Integer;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

function TForm1.SomeFunc: Integer;
begin
 Result := 5;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 F: TForm1;
begin
 Caption := IntToStr(F.SomeFunc);
end;


Отработает и ни на что не ругнётся, потому что к полям объекта нет обращений внутри функции. Ей абсолютно пофиг что в EAX мусор, она всё-равно туда результат запишет.


 
TUser ©   (2004-07-06 07:52) [5]

В живом примере тоже вызывается конструктор, просто Борланд освободил тебя от этих забот.
А отличаются они примерно так. Возьмем объект "программист Delphi". Его можно просклонять (один программист, много программисток), это - мотод класса. А вот напоить пивом можно только конкретный экземпляр программиста.


 
MBo ©   (2004-07-06 08:06) [6]

обычный метод представляет собой структуру TMethod, содержащую указатели на адрес данной функции в классе (Code), и указатель на сам объект (Data), по этому адресу хранятся данные конкретного экземпляра (выделение памяти осуществляется при вызове конструктора классовой функцией NewInstance). Self в обычно методе - указатель на экземпляр объекта, в классовом - на сам класс.


 
SPeller ©   (2004-07-06 08:32) [7]


> TUser ©   (06.07.04 07:52) [5]
> В живом примере тоже вызывается конструктор, просто Борланд
> освободил тебя от этих забот.

Нет, ничего там не вызывается. Проверьте сами, если не верите.


> MBo ©   (06.07.04 08:06) [6]
> в классовом - на сам класс

То есть, на саму структуру класса, по которой создаются все экземпляры класса?


 
MBo ©   (2004-07-06 08:46) [8]

>То есть, на саму структуру класса, по которой создаются все экземпляры класса?
Да, можно так сказать.


 
TUser ©   (2004-07-06 08:47) [9]

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
 Instance: TComponent;
begin
 Instance := TComponent(InstanceClass.NewInstance);
 TComponent(Reference) := Instance;
 try
   Instance.Create(Self);
 except
   TComponent(Reference) := nil;
   raise;
 end;
 if (FMainForm = nil) and (Instance is TForm) then
 begin
   TForm(Instance).HandleNeeded;
   FMainForm := TForm(Instance);
 end;
end;


ЗЫ. Объект Форма не может возникнуть сам собой - без конструктора.


 
SPeller ©   (2004-07-06 08:56) [10]


> Да, можно так сказать.

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


 
KSergey ©   (2004-07-06 08:57) [11]

> [9] TUser ©   (06.07.04 08:47)

Вы в код из [4] SPeller ©   (06.07.04 07:36) внимательно вчитаетесь наконец?
А то, что "живой пример" работает - я склонен списать на случайности. В общем случае не любой указатель является заведомо таким, что обязтельно будет AV.


 
SPeller ©   (2004-07-06 08:58) [12]


> TUser ©   (06.07.04 08:47) [9]

Посмотрите внимательно на этот кусок кода:

var
  F: TForm1;
begin
  Caption := IntToStr(F.SomeFunc);


Где здесь что-либо создается?


 
SPeller ©   (2004-07-06 09:02) [13]


> А то, что "живой пример" работает - я склонен списать на
> случайности

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


 
TUser ©   (2004-07-06 09:06) [14]

Да, правда. Невнимателен был, прошу пардона.


 
GuAV ©   (2004-07-06 11:43) [15]

короче, напиши
var
 C: TComponent
begin
 C. {задумайся, всплывет подсказка, в ней все методы}
 TComponent. {задумайся, всплывет подсказка, в ней только классовые методы}


 
GuAV ©   (2004-07-06 11:48) [16]

SPeller ©   (06.07.04 09:02) [13]

да. но чтобы не путать методы, которые не работают с полями и могут работать для несозданных классов с обычными вели класовые методы. и потом есть функции которым передается TClass или какойто ещё class of. и потом, у классового self"ом при вызове как классового в self будет class


 
GuAV ©   (2004-07-06 11:57) [17]


> TClass или какойто ещё class of


> в self будет class

я имел ввдиу class-reference или metaclass.

Без этой фичи в Delphi они были бы бесполезны.


 
Юрий Зотов ©   (2004-07-06 12:14) [18]

> SPeller ©   (06.07.04 08:56) [10]

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

Можно: Self.InstanceSize.

В классовых методах неявный параметро Self - это ссылка на класс (в обычных - на экземпляр класса). InstanceSize - тоже классовый метод, поэтому его можно вызывать и через ссылку не класс.


 
GuAV ©   (2004-07-06 12:51) [19]


> В классовых методах неявный параметро Self - это ссылка
> на класс (в обычных - на экземпляр класса)

Но если классовый метд вызван как обычный через экземпляр, то у него и self как у обычного.


 
MBo ©   (2004-07-06 13:50) [20]

>GuAV ©   (06.07.04 12:51) [19]
>Но если классовый метд вызван как обычный через экземпляр, то у него и self как у обычного.

Да ну? ;))

TC=class
 class function ClassMe:Pointer;
 function Me:Pointer;
end;

class function TC.ClassMe: Pointer;
begin
Result:=Self;
end;

function TC.Me: Pointer;
begin
Result:=Self;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 c:TC;
begin
 c:=TC.Create;
 Caption:=Format("%p %p %p",[TC.ClassMe,c.ClassMe,c.Me]);
 c.Free;
end;


 
Юрий Зотов ©   (2004-07-06 14:01) [21]

> GuAV ©   (06.07.04 12:51) [19]

Очень похоже, что Delphi с Вами не согласна.


type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 public
   class procedure A;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

class procedure TForm1.A;
begin
 if Self = TForm1 then
   ShowMessage("класс")
 else
   ShowMessage("не класс")
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Form1.A  // И получаем сообщение "класс"
end;


А вот что показывает ассемблерный код Button1Click:


mov  eax, [Form1] ; в eax - ссылка на экземпляр
mov  eax, [eax]   ; в eax - ссылка на класс
call TForm1.A     ; и только теперь - вызов


Я полагаю, что компилятору верить можно...
:о)


 
GuAV ©   (2004-07-06 14:07) [22]


> Очень похоже, что Delphi с Вами не согласна.

Извините, ошибся, хелп не правильно перевел :-(


 
SPeller ©   (2004-07-06 17:00) [23]

Большое всем спасибо за столь подробные разъяснения! Чтобы не докучать вопросами, было бы очень интересно самому почитать про внутреннюю организацию классов и объектов (object). Если кто подскажет где можно почитать буду очень благодарен. )


 
Amoeba ©   (2004-07-06 17:02) [24]

На сайте Анатолия Подгорецкого полно литературы.


 
Тимохов ©   (2004-07-06 17:20) [25]


> SPeller ©   (06.07.04 17:00) [23]

ничего нет лучше, чем часто вызвать окно cpu (главное меню\view\debug windows) и см. асм код.

ЗЫ
я асм не знаю (совсем), но часто мне кажется, что что-то понимаю :))) Иногда ошибаюсь правда, но все же польза от изучения cpu есть


 
Анонимщик ©   (2004-07-06 18:07) [26]

Speller

Хелп на слово VMT. Остальное несложно сообразить. Полезно также посмотреть, что происходит при запуске программы, в частности,
InitExe, StartExe.
А также структуру PE-файла.


 
Тимохов ©   (2004-07-06 18:10) [27]


> Анонимщик ©   (06.07.04 18:07) [26]
> InitExe, StartExe.

Где это можно посмотреть?


 
Анонимщик ©   (2004-07-06 18:33) [28]

Под отладчиком лучше всего и смотреть. Оно все в SysInit.pas


 
SPeller ©   (2004-07-07 03:27) [29]


> А также структуру PE-файла.

Ой, мне ли вы это будете рассказывать? :-)))


> ничего нет лучше, чем часто вызвать окно cpu (главное меню\view\debug
> windows) и см. асм код.

АСМ код не покажет структуру сласса и расположение в ней элементов различных. А то что смотреть в окошко cpu полезно — я сам знаю :)


 
Тимохов ©   (2004-07-07 08:54) [30]


> АСМ код не покажет структуру сласса и расположение в ней
> элементов различных.

это как смотреть: в свое время я именно так и понял много вещей.


 
Анонимщик ©   (2004-07-07 11:11) [31]

Почитав справку по VMT, ты поймешь, где находятся поля и методы по отношению к адресу класса или объекта, а из PE формата нужно только знать, как вытащить адрес сегмента кода и сегмента данных. После этого сам можешь построиь, например, дерево классов с адресами полей и т.д. С абсолютного нуля разберешься со всем за неделю, это точно.



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

Форум: "Основная";
Текущий архив: 2004.07.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.037 c
3-1087770767
Stalker
2004-06-21 02:32
2004.07.18
InterBase, даты....


3-1087995468
peypivo
2004-06-23 16:57
2004.07.18
firebird


1-1088751012
b-a-n
2004-07-02 10:50
2004.07.18
Занимаемая программой память


14-1088602579
pasha_golub
2004-06-30 17:36
2004.07.18
Помогите с Java


14-1088240303
YurikGL
2004-06-26 12:58
2004.07.18
Во дают!





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