Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

ООП и др.

6.9K
01 апреля 2006 года
Britney
69 / / 20.03.2006
Помогите кое в чем разобраться!
1. Паскале есть зарезервированные слова Record, Class (на счет этого не уверен), Object, подскажите в чем различие (какое когда нужно использовать)
2. Нашел на сайте http://rrc.dgu.ru/res/www.isu.ru/~slava/teach/delphi/Curses/Problems/4.htm следующее:

Особенности языка Object Pascal в Delphi

Структура файла проекта и модулей

Существенные отличия языка
- классы
- class и object. Ссылки и значения. TObject.
- Динамические и статические экземпляры объектов.

{ Старая объектная модель }
type
PMyObject = ^TMyObject;
TMyObject = object (TObject)
MyField : PMyType;
constructor Init;
end;
var
MyObject : PMyObject;
begin
MyObject:=New(PMyObject,Init);
MyObject^.MyField:= ...
end;

{ Новая объектная модель }
type
TMyObject = class(TObject)
MyField : TMyType;
end;
var
MyObject : TMyObject;
begin
MyObject:=TMyObject.Create;
MyObject.MyField:= ...
end;


Т.е. в дельфи не используется Object, а надо писать Class, и при этом сразу же все классы, переменные, процедуры и функции обозначаются как динамические?
И еще подскажите, что за класс TObject - описания его не вижу, он изначально существует?
10
01 апреля 2006 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Britney
Особенности языка Object Pascal в Delphi


Обсуждалось.

2.0K
01 апреля 2006 года
Neko
25 / / 14.11.2002
Delphi 7 help :
"TObject is the ultimate ancestor of all objects and components."

Поищи в хелпе про TObject там есть.

Насколько я понимаю отличия record от class - то оно аналогично отличию "структуры" от "класса" в С++.
6.9K
01 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by Freeman
Обсуждалось.



Все отлично, вчитался, узнал много нового, но там ни слова не сказано когда нужно применять class, когда object, а когда record.
А еще не понятно, про динамическую память (конец первого сообщения)

10
01 апреля 2006 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Britney
но там ни слова не сказано когда нужно применять class, когда object, а когда record.


Зависит от задачи.

Цитата:
А еще не понятно, про динамическую память (конец первого сообщения)


Вопрос некорректен.

5
01 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Britney
Все отлично, вчитался, узнал много нового, но там ни слова не сказано когда нужно применять class, когда object, а когда record.

использование object в Delphi - это архаизм. они не используются и оставлены в языке для обратной совместимости. Для реализации ООП в Delphi предусмотрены class'ы.

А record можно юзать во всех остальных случаях, например для хранения массива какой-нибудь структурированной инфы, когда создавать экземпляры class'ов муторно и неудобно.

6.9K
03 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by Britney

{ Старая объектная модель }
type
PMyObject = ^TMyObject;
TMyObject = object (TObject)
MyField : PMyType;
constructor Init;
end;
var
MyObject : PMyObject;
begin
MyObject:=New(PMyObject,Init);
MyObject^.MyField:= ...
end;

{ Новая объектная модель }
type
TMyObject = class(TObject)
MyField : TMyType;
end;
var
MyObject : TMyObject;
begin
MyObject:=TMyObject.Create;
MyObject.MyField:= ...
end;


Остается непонятным вид новой объектной модели в сравнении со старой (этот код я взял из какого-то учебника указанного в ссылке). Как следует из примера, в старой объектной модели требовалось ручками прописать, что тип PMyObject является динамическим. В новой же тип TMyObject является динамическим изначально (потому что является потомком типа TObject) для него не требуется применять операцию выделения памяти и всё с этим связанное. В таком случае класс TObject является динамическим.Я правильно понял(исходя только из листинга)?

303
04 апреля 2006 года
makbeth
1.0K / / 25.11.2004
Цитата:
Originally posted by Britney
Остается непонятным вид новой объектной модели в сравнении со старой (этот код я взял из какого-то учебника указанного в ссылке). Как следует из примера, в старой объектной модели требовалось ручками прописать, что тип PMyObject является динамическим. В новой же тип TMyObject является динамическим изначально (потому что является потомком типа TObject) для него не требуется применять операцию выделения памяти и всё с этим связанное. В таком случае класс TObject является динамическим.Я правильно понял(исходя только из листинга)?


Что это за понятие - динамический тип? Все гораздо проще: в "старом" паскале объектная модель является аналогом C++ модели, т.е. все типы object являются аналогом class в C++. Объявление переменной например MyObject: TMyObject автоматически создает объект MyObject и под него выделяется память (если объявление находиться в процедуре функции, то память выделяется в стеке, если переменная объявляется в в модуле, то память - глобальная). Чтобы создать объект динамически, то необходимо объявлять тип указатель на объект (PMyObject = ^TMyObject), поскольку при динамическом выделении блока памяти, необходим указатель, который указывает на этот блок.

Код:
type
     PMyObject = ^TMyObject;
     TMyObject = object
     private
         X: Integer;
     public
         constructor Init;
         procedure SetX(Value: Integer);
     end;

constructor TMyObject.Init;
begin
    X:=0;
end;

procedure TMyObject.SetX(Value: Integer);
begin
    X:=Value;
end;

procedure ManageObjects;
var MyObject: TMyObject; // Создан объект в стеке
    pMyObj: PMyObject;
begin
    MyObject.Init; // X:=0;
    MyObject.SetX(100); // Нормальная работа с объектом
    // pMyObj^.Init - ошибка, указатель ни на что не ссылается
    pMyObj:=New(PMyObject, Init); // Создаем объект в динамической памяти и
    // вызываем его метод Init
    pMyObj^.SetX(100); // Теперь все нормально
    Dispose(pMyObj); // Освобождаем память
end;

Так было в "старом" паскале.
В Object Pascal совершенно другой подход к созданию объектов. Объявление переменной некоего класса, где бы она не была объявлена, не приводит к созданию объекта как такового. Будет объявлена только ссылка на него (считай, указатель), ни на что не ссылающаяся.
Код:
type
     TMyObject = class
     private
         X: Integer;
     public
         constructor Create;
         procedure SetX(Value: Integer);
     end;

constructor TMyObject.Create;
begin
    inherited; // Вызов конструктора базового класса обязателен
    X:=0;
end;

procedure TMyObject.SetX(Value: Integer);
begin
    X:=Value;
end;

procedure ManageObjects;
var MyObject: TMyObject; // Объявлена ссылка на объект
begin
    // MyObject.SetX(100); // Здесь возникнет исключение Access violation (попытка обращения к несуществующему адресу памяти)
    MyObject:=TMyObject.Create; // Создаем объект в динамической памяти
    MyObject.SetX(100); // Теперь все нормально
    MyObject.Free; // Освобождаем память
end;

Еще остается добавить, что все классы в Object Pascal наследуются от класса TObject, задача которого - выделение памяти под объект и инициализация всех полей класса нулевыми значениями.
А вообще стоит купить какую нибуть хорошую книгу (к примеру М. Канту) и прочитать :) Еще рекомендую почитать статьи в разделе "Лицей" на Королевстве Дельфи. Успехов!
2.0K
04 апреля 2006 года
Neko
25 / / 14.11.2002
Цитата:
Originally posted by makbeth
Что это за понятие - динамический тип? Все гораздо проще: в "старом" паскале объектная модель является аналогом C++ модели, т.е. все типы object являются аналогом class в C++. Объявление переменной например MyObject: TMyObject автоматически создает объект MyObject и под него выделяется память (если объявление находиться в процедуре функции, то память выделяется в стеке, если переменная объявляется в в модуле, то память - глобальная). Чтобы создать объект динамически, то необходимо объявлять тип указатель на объект (PMyObject = ^TMyObject), поскольку при динамическом выделении блока памяти, необходим указатель, который указывает на этот блок.

Так было в "старом" паскале.
В Object Pascal совершенно другой подход к созданию объектов. Объявление переменной некоего класса, где бы она не была объявлена, не приводит к созданию объекта как такового. Будет объявлена только ссылка на него (считай, указатель), ни на что не ссылающаяся.


Вот это и есть динамический объект. Его можно создавать в любом месте программы. Можно несколько раз.

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

6.9K
04 апреля 2006 года
Britney
69 / / 20.03.2006
Огромное спасибо за исчерпывающие ответы! Приятно, что на этом форуме есть столько людей, которые действительно знают Delphi и могут помочь человеку!
5
04 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Neko
И я не понял почему ты именно старую модель сравниваешь с С++??? Class - это как раз динамический тип, а в старой модели - статический. Новая модель на много больше похожа на сишную.


Ты в этом точно уверен? :D :D
Значит ты не разобрался с семантикой ООП в С++ :P

В С++ при объявлении экземпляра некоторого класса вызов конструктора происходит автоматически. А чтоб создавать объект тогда, когда мы хотим, нам нужно объявлят указатель на объект в явном виде, чего не требуется делать, когда мы используем "новую" парадигму ООП в Делфи.

А то, что ты называешь "похожестью" на модель ООП в С++, то это - просто проявление хорошей реализации ООП в Делфи. Кроме того Борланд ведёт параллельно С++ Билдер и Делфи, которые используют единую библиотеку классов VCL.

6.9K
05 апреля 2006 года
Britney
69 / / 20.03.2006
Хорошо, тогда у меня есть еще один вопрос по поводу динамических массивов.
Описать дин. массив можно так:
var DMas:array of char;
После чего в программе надо задать его длину:
SetLength(DMas,16);
До этого момента я все правильно написал!

Далее. У меня есть функция, в из которой по ссылке передается динамический массив:
Например,
function FUN(var M:array of char):word;
var i:integer;
begin
....
for i:=1 to 15 do
M:='{символ}';
result:=i;
end;
{все написано для примера}

После этого мне надо из программы вызвать эту функцию и получить значения массива М из нее:

var DMas:array of char;
a:integer;
begin
SetLength(DMAS,16);
a:=FUN(DMAS);
end.

Но вместо того, чтобы выполниться, он говорит о несовпадении типов Array и DynamicArray
В чем байда?
4.5K
05 апреля 2006 года
StranikS
44 / / 03.02.2005
Цитата:
Originally posted by Britney
Хорошо, тогда у меня есть еще один вопрос по поводу динамических массивов.
Описать дин. массив можно так:
var DMas:array of char;
После чего в программе надо задать его длину:
SetLength(DMas,16);
До этого момента я все правильно написал!

Далее. У меня есть функция, в из которой по ссылке передается динамический массив:
Например,
function FUN(var M:array of char):word;
var i:integer;
begin
....
for i:=1 to 15 do
M:='{символ}';
result:=i;
end;
{все написано для примера}

После этого мне надо из программы вызвать эту функцию и получить значения массива М из нее:

var DMas:array of char;
a:integer;
begin
SetLength(DMAS,16);
a:=FUN(DMAS);
end.

Но вместо того, чтобы выполниться, он говорит о несовпадении типов Array и DynamicArray
В чем байда?





Типичная ошибка в коде:
Функции и процедуры не позволяют описывать массивы в области задания входных и выходных параметров.
Поэтому тебе надо было объявить тип и уже рабоатать через него:

Код:
type
   Mas_CHAR=array of char;
...
function FUN(var M:Mas_CHAR):word;
var i:integer;
begin
....
for i:=1 to 15 do
M:='{символ}';
result:=i;
end;

var DMas:Mas_CHAR;
    a:integer;
begin
SetLength(DMAS,16);  
a:=FUN(DMAS);
end.
6.9K
05 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by StranikS
Типичная ошибка в коде:
Функции и процедуры не позволяют описывать массивы в области задания входных и выходных параметров.
Поэтому тебе надо было объявить тип и уже рабоатать через него:


Ни фига - в паскале нельзя, а дельфи можно. Можно объявиться массив как обычно в этих самых областях
function FUN(var Mas:array of char):word;
и сама функция работает(проверял через степинг).
Но при ее вызове в программе возникает ошибка несовместимости типов статических и динамических.
Т.е. если эту самую функцию вызвать в программе,
то возвращаемый массив должен быть описан как статический,
т.е:

 
Код:
var DMas:array[1..16] of char;
a:integer;
begin
a:=FUN(DMAS);
end.

Так все работает, но теряется смысл использования динамических массивов.
10
05 апреля 2006 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Britney
Так все работает, но теряется смысл использования динамических массивов.


Ни фига не теряется. Надо внимательней курить доку.

Конструкция array of без указания размерности в описании типа описывает динамический массив, а в заголовке процедуры, т. н. открытый массив. Его еще можно назвать встроенным (inline) динамическим массивом. С точки зрения Object Pascal это другая синтаксическая конструкция, выступающая в качестве альтернативы объявлению переменного числа параметров в Си. Так, например, объявлена функция Format.

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

6.9K
05 апреля 2006 года
Britney
69 / / 20.03.2006
Да я как бы и не прочь описать как отдельный тип и даже пытался, но функция является методом класса
Type
Form1 = class(TFORM)
.........
end;

////1////
TTPS = class
.........
function FUN(var Mas:array of char):word;
end;

end;
implementation
////2///
begin
......
end.

Вопрос заключается в том, где этот самый тип надо описывать?Если описать его перед TTPS, то возникает какая-то ошибка, если в разделе implementation, то снова какая-то ошибка (честно говоря не помню какая - вчера вечером этим занимался и еще дома не был)
6.9K
05 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by Freeman
Ни фига не теряется. Надо внимательней курить доку.

Конструкция array of без указания размерности в описании типа описывает динамический массив, а в заголовке процедуры, т. н. открытый массив. Его еще можно назвать встроенным (inline) динамическим массивом. С точки зрения Object Pascal это другая синтаксическая конструкция, выступающая в качестве альтернативы объявлению переменного числа параметров в Си. Так, например, объявлена функция Format.

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


Т.е. ты хочешь сказать, что массив описанный в программе
var DMas:array[1..16] of char;
тоже является динамическим. Но если так, то как его уничтожить после того, как он стал не нужен?

10
05 апреля 2006 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Britney
Т.е. ты хочешь сказать, что массив описанный в программе
var DMas:array[1..16] of char;


Ключевое слово в моей фразе - без указания размерности.

Цитата:
var DMas:array[1..16] of char;
тоже является динамическим. Но если так, то как его уничтожить после того, как он стал не нужен?


RTFM, RTFM и еще раз RTFM!

339
05 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by Britney
Да я как бы и не прочь описать как отдельный тип...
Вопрос заключается в том, где этот самый тип надо описывать?Если описать его перед TTPS, то возникает какая-то ошибка, если в разделе implementation, то снова какая-то ошибка (честно говоря не помню какая - вчера вечером этим занимался и еще дома не был)



рабочий код...

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

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

  TMyMas = Array of Char;

  TTPS = class
    function FUN(Mas: TMyMas): Word;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TTPS }

function TTPS.FUN(Mas: TMyMas): Word;
var
  I: Integer;
begin
  I := 0;
  while I < Length(Mas) do begin
    Mas := '1';
    Inc(I);
  end;
  Result := I;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TPS: TTPS;
  Mas: TMyMas;
begin
  TPS := TTPS.Create;
  SetLength(Mas, 10);
  TPS.FUN(Mas);
  TPS.Free;
end;

end.
339
05 апреля 2006 года
verybadbug
619 / / 12.09.2005
единственный глюк, который может здесь возникнуть - FUN возвращает WORD, а используется там для вычислений Integer... т.е. может, в зависимости от выполняемых действий, некорректное значение возвращать... :!!!:
6.9K
06 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by verybadbug
единственный глюк, который может здесь возникнуть - FUN возвращает WORD, а используется там для вычислений Integer... т.е. может, в зависимости от выполняемых действий, некорректное значение возвращать... :!!!:


ОГРОМНОЕ БЛАГОДАРЮ!!!!!!!!!!!!!
А еще такой вопрос: можно ли функцию описать как массив? например так:
function FUN(i:word): array of char;
?

339
07 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by Britney
А еще такой вопрос: можно ли функцию описать как массив? например так:
function FUN(i:word): array of char;
?



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

 
Код:
...
  TMyMas = Array of Char;
...
  function FUN(I: Word): TMyMas;
...
6.9K
07 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by verybadbug
сам не знаю.... попробуй... только массив нужно указывать не в явном виде.... т.е.

 
Код:
...
  TMyMas = Array of Char;
...
  function FUN(I: Word): TMyMas;
...



Да, получилось!Это большой прорыв - теперь у меня развязываются руки!!!
Вызов функции производится так:
...:=a(i)[j];
но это для статического массива(type TMyMas = Array[1..100] of char)!
А вот с динамическим какой-то напряг! И спец. функции для выделения памяти для массивов-функций нет!!! Может у кого-нить есть какие-нить варианты?

5
07 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Britney
...:=a(i)[j];


Конечно замечательно, но если это в цикле, то хочу поздравить: ты получил жутко неэффективный код. НА КАЖДОМ i и j (т.е. i*j раз вместо i требуемых) у тебя происходит вычисление функции a(i), которая вовращает МАССИВ.
А понятия "Функция-массив" в паскале нету.

Кроме того возращать статический массив из функции как результат - жэто крайне неэффективно, ну представь, функция сначала заполяет массив, а после её вызова её массив-результат копируется в нужную переменную! Поэтому чтобы вернуть статический массив нужно использовать out- или var-параметры.

возвращать динамический массив - это уже выход. программно динамический массив представляется как указатель на область памяти, где находится сам массив (+ кое-какая инфа). Размер динамического массива получать можно функцией Length.


Т.о. лучше делать так (псевдокод):
arr - массив
a(i) возвращает динамический массив

 
Код:
for i do begin
  arr:=a(i)
  ...
  for j do begin
  ...arr[j]...
  end;
end;
339
07 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by Britney
Может у кого-нить есть какие-нить варианты?



Вобщем забудь про статику.... используй динамические массивы....

размер массива i := Length(MyMas)

установка размера перед определением значений его элементов SetLength(MyMas, Size)

и ещё кое что... если массив уже имеет определённый размер, а тебе его нужно уменьшить - используй SetLength(MyMas, Length(MyMas) - 1),
а для увеличения SetLength(MyMas, Length(MyMas) + 1), при этом все элементы до Length - 1 сохраняют своё значение....

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог