Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.18;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.022 c
14-1088582593
GanibalLector
2004-06-30 12:03
2004.07.18
ДОСТУП ЗАБЛОКИРОВАН


4-1086534421
akvilon
2004-06-06 19:07
2004.07.18
Как измерить длину текстовой строки (в пикселах)


3-1087991058
dns
2004-06-23 15:44
2004.07.18
Соединение Table


4-1086615887
Sirakuz
2004-06-07 17:44
2004.07.18
Reference Count и LoadLibrary


14-1088512308
Kolyan
2004-06-29 16:31
2004.07.18
Линукс и Фат разделы