Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вызов деструктора внутри конструктора 
:(
    Опции темы
Демо
Дата 3.6.2010, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 7
Всего: 50




Код

  TMyObject=class
  private
    FName: String;
    FS: TFileStream;
  public
    constructor CreateObj(const FilePath: String);
    destructor Destroy; override;
    class function Create(const FilePath: String): TMyObject;
  end;



Код

{ TMyObject }

class function TMyObject.Create(const FilePath: String): TMyObject;
begin
  Result := nil;
  if not FileExists(FilePath) then Exit;
  try
    Result := TMyObject.CreateObj(FilePath);
  except
// Нам всё равно, что за исключение. Гасим его
  end;
end;

constructor TMyObject.CreateObj(const FilePath: String);
begin
  FName := FilePath;
  FS := TFileStream.Create(FName,fmOpenRead);
end;

destructor TMyObject.Destroy;
begin
  FS.Free;
  inherited;
end;




--------------------
    
PM MAIL ICQ Skype   Вверх
CodeMonkey
Дата 3.6.2010, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Цитата(PsiMagistr @  3.6.2010,  14:12 Найти цитируемый пост)
Неплохо было бы в деструкторе класса прописать чтобы указатель получал хотя бы Nil

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

Но если сильно охота, то можно - в качестве примера посмотрите реализацию Application.CreateForm (вызов смотреть в DPR-файле, а реализацию - в Forms.pas). Но делать так без веских причин я бы не стал.

Цитата(PsiMagistr @  3.6.2010,  14:12 Найти цитируемый пост)
Вы пишите If Assigned(self) then в деструкторе лишняя? Вот тут я не могу понять, почему?

Потому что Self = nil в деструкторе - это глюк (почему? уже сказал Demo: при вызове из конструктора Self гарантировано не-nil, а при внешнем вызове вы вызываете Free; хотя формально вы вполне можете вызывать TForm(nil).Destroy). Такого не должно быть. А раз не должно быть, то вылететь с access violation - вполне нормальный вариант. Можете не засорять исходники лишними проверками.

Цитата(Демо @  3.6.2010,  16:16 Найти цитируемый пост)
Вместо всего этого достаточно

Только надо понимать, что "достаточно" <> "нужно так делать".

Цитата(PsiMagistr @  3.6.2010,  16:39 Найти цитируемый пост)
Я полагал, что предок всегда есть (TObject хотя бы).

Верно.

Цитата(PsiMagistr @  3.6.2010,  16:39 Найти цитируемый пост)
Правильно ли я вас понял, что невозможно вызвать деструктор для несуществующего объекта?

Сделать можно что угодно:

Код
TForm(nil).Destroy;


Но тогда вы сами себе буратино.

Цитата(PsiMagistr @  3.6.2010,  16:39 Найти цитируемый пост)
Мне важно, чтобы в MyObject был nil. Но вот как его туда заслать?  Ведь при исключении тут же вызывается деструктор, который разрушает все и в конечном итоге - мусор в MyObject.


Код
MyObject := nil;
MyObject := TMyObject.Create('filename');

// или:

try
  MyObject := TMyObject.Create('filename');
except
  MyObject := nil;
  raise;
end;


Цитата(PsiMagistr @  3.6.2010,  18:36 Найти цитируемый пост)
Но проверка на nill  не в конструкторе, она внешняя, из программы, в обработчике кнопки. По идее должен был быть переход к след шагу, неужели же обваливается вся процедура, где этот злосчастный конструктор вызван? Но тогда получается что из за исключения в конструкторе вся программа клеит ласты)))

Рекомендую почитать.

Добавлено через 5 минут и 22 секунды
Согласен с bems-ом по поводу деструктора.

Цитата(Демо @  3.6.2010,  20:09 Найти цитируемый пост)
Это ещё почему?

По той простой причине, что пустой конструктор - это деталь реализации, а не стандарт ООП языка. Вот выйдет Fulcrum - откуда вы знаете, может там в деструкторе что-то будет, чтобы сгладить косяки платформы? Вы уверены, что в FreePascal (подставьте сюда любой компилятор Паскаля, с которым вы не знакомы) деструктор тоже пустой?

Но это не главное. А главное в том, что класс может быть изменён в процессе рефакторинга позже. В том числе, он может сменить предка. Вызов унаследованных конструкторов и деструкторов всегда - это простое правило, которое поможет вам избежать потенциальных проблем.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Демо
Дата 3.6.2010, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 7
Всего: 50



Цитата(CodeMonkey @  3.6.2010,  20:32 Найти цитируемый пост)
По той простой причине, что пустой конструктор - это деталь реализации, а не стандарт ООП языка. Вот выйдет Fulcrum - откуда вы знаете, может там в деструкторе что-то будет, чтобы сгладить косяки платформы? Вы уверены, что в FreePascal (подставьте сюда любой компилятор Паскаля, с которым вы не знакомы) деструктор тоже пустой?Но это не главное. А главное в том, что класс может быть изменён в процессе рефакторинга позже. В том числе, он может сменить предка. Вызов унаследованных конструкторов и деструкторов всегда - это простое правило, которое поможет вам избежать потенциальных проблем.


Да согласен я-)

Смысл фразы в том, что нужно всегда знать, что делаешь.
Если я знаю в данный момент, что в TObject мне ничего не нужно освобождать, то с полным сознанием и уверенностью могу не вызывать родительский деструктор, учитывая, что другоим колмпилятором я не буду пользоваться...




--------------------
    
PM MAIL ICQ Skype   Вверх
bems
Дата 4.6.2010, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



Цитата(Демо @  3.6.2010,  19:09 Найти цитируемый пост)
Это ещё почему?
Потому что очень трудно следить за каждым конструктором на предмет озможности исключений. Правильнее считать что исключение может возникнуть в любом месте любого конструктора (собственно это не далеко от истины). Если моих слов не достаточно то вот:
Цитата(http://docwiki.embarcadero.com/RADStudio/en/Methods)
When an exception is raised during the creation of an object, Destroy is automatically called to dispose of the unfinished object. This means that Destroy must be prepared to dispose of partially constructed objects. Because a constructor sets the fields of a new object to zero or empty values before performing other actions, class-type and pointer-type fields in a partially constructed object are always nil. A destructor should therefore check for nil  values before operating on class-type or pointer-type fields. Calling the Free method (defined in TObject) rather than Destroy offers a convenient way to check for nil  values before destroying an object. 

А твой пример ни к селу ни к городу. Ясно, что если деструктор ничего не делает, то и проверять нечего (даже если бы в конструкторе TObject и могло возникнуть исключение)

Добавлено через 12 минут и 42 секунды
Цитата(CodeMonkey @  3.6.2010,  20:32 Найти цитируемый пост)
Согласен с bems-ом по поводу деструктора.
...
Вызов унаследованных конструкторов и деструкторов всегда - это простое правило, которое поможет вам избежать потенциальных проблем.

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


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Демо
Дата 4.6.2010, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 7
Всего: 50



Цитата(bems @  4.6.2010,  00:33 Найти цитируемый пост)
что-то меня не поняли. Я говорил не о вызове унаследованного деструктора, а о том, чтобы всегда писать деструктор так, чтобы он мог разрушать недосозданный объект


Действительно не поняли.
Я-то говорил именно об обязательности вызова родительского деструктора.


--------------------
    
PM MAIL ICQ Skype   Вверх
bems
Дата 4.6.2010, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



Цитата(Демо @  3.6.2010,  19:52 Найти цитируемый пост)
// Нам всё равно, что за исключение. Гасим его

Даже если это нехватка памяти или Assert?


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Демо
Дата 4.6.2010, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 7
Всего: 50



Цитата(bems @  4.6.2010,  01:28 Найти цитируемый пост)
Даже если это нехватка памяти или Assert?


Ну если нехватка памяти, то вряд ли можно что-то ещё сделать.
А работу с Assert надо заранее проектировать-)


--------------------
    
PM MAIL ICQ Skype   Вверх
PsiMagistr
Дата 4.6.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Ребята, благодарю всех. Огромное СПС! Сейчас читаю информацию предоставленную, CodeMonkey :

Итак как я сделал:

Реализация конструктора:

Код

constructor TMyClass.Create(FileName:String);
begin
inherited Create; //Вызов конструктора предка.
if FileExists(ExtractFilePath(Application.ExeName)+FileName) = true then //Если файл есть то:

begin
Fname := 'Умолчание';  //Присваиваем значение по умолчанию полю FName
ShowMessage('Есть!'); //
end

Else raise Exception.Create('Нет файла!');
end;



Реализация деструктора:

Код

Destructor TMyClass.Destroy;
Begin
ShowMessage('Вызываю деструктор!');
Inherited Destroy;
end;




А в коде кнопки:

Код

procedure TForm1.Button1Click(Sender: TObject);

begin
MyObject:= nil;

try
MyObJect:=TMyClass.Create('Проба.txt'); //Пытаюсь создать конструктор

Except //И словить исключение:

if MyObject = nil then ShowMessage('Указатель Нулевоой');
end;
end;


Запускать это из самой среды бесполезно - Дельфи споткнется в конструкторе. Поэтому компилирую файл. Все как будто получается. И деструктор вызывается. Но таблички:

Код

Else raise Exception.Create('Нет файла!'); //Не возникает.





 

Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 12:41


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 4.6.2010, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Код
if FileExists(ExtractFilePath(Application.ExeName)+FileName) = true then


= True - излишне. Это всё равно, что спрашивать "если да равно да то" или "включен ли компьютер" (если бы компьютер был бы выключен, программа не смогла бы задать этот вопрос).

Надо:
Код
if FileExists(ExtractFilePath(Application.ExeName)+FileName) then


Цитата(PsiMagistr @  4.6.2010,  13:12 Найти цитируемый пост)
Дельфи споткнется в конструкторе

Это уведомление отладчика сделано исключительно для вашего удобства, чтобы вы могли исследовать ситуацию, приводящую к ошибке, прямо на месте. Если вы не хотите этого делать - просто жмите Continue (в новых Delphi) или Run/Run (в старых).

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

Цитата(PsiMagistr @  4.6.2010,  13:12 Найти цитируемый пост)
Но таблички Не возникает

Вы же сами её заблокировали блоком except.

Далее, проверять в except MyObject на nil - излишне, т.к. если вы попали в блок except, то только потому, что создание объекта обвалилось. Это всё равно, что проверять Self <> nil в деструкторе. Поэтому:

Код
try
  MyObJect:=TMyClass.Create('Проба.txt'); //Пытаюсь создать конструктор
Except //И словить исключение:
  MyObJect:=nil;
  ShowMessage('Указатель Нулевоой');
end;
end;


А вот и табличка:

Код
try
  MyObJect:=TMyClass.Create('Проба.txt'); //Пытаюсь создать конструктор
Except //И словить исключение:
  MyObJect:=nil;
  ShowMessage('Указатель Нулевоой');
  raise;
end;
end;


Или:

Код
try
  MyObJect:=TMyClass.Create('Проба.txt'); //Пытаюсь создать конструктор
Except //И словить исключение:
  MyObJect:=nil;
  ShowMessage('Указатель Нулевоой');
  Application.HandleException(nil);
end;
end;


В общем, миллион способов. А выбор зависит от того, зачем это надо, и что вы будете делать дальше. И я бы, на вашем месте, рассказал бы побольше про это.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 4.6.2010, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Я попробую в двух словах. Решил писать ролевую игру. Когда то давно писал на VB первый экземпляр. Получилось. Правда реализовывать ООП я не стал, обошелся процедурным программированием.

Основная текущая задача - зашить в класс работу с файлами. 

Вот например файл персонажа. Изначально там служебная информация, недоступная игроку. (параметры умолчания).

Например:

Жизнь-100
Интеллект-50
Ловкость=30

И .т.д. 

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

В классе я пытаюсь охватить все возможные нюансы работы с файлами. Например обращение из основной программы:

MyObject.Lovkost:=30; 

к свойству "Ловкость", будет означать не только присвоение, но и запись соответствующей информации в файл.









Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 13:04


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 4.6.2010, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Так, а теперь, внимание, вопрос (С)

Положим вы создаёте персонажа из файла TMyObject.Create('SavedGame01.dat');

Положим файл не найден, заблокирован антивирусом или тупо повреждён - вы выбрасываете исключение, отлично.

Но. Дальше-то вы что делаете? А дальше вы обрабатываете эту ошибку, показывая мессагу, производя откат или что там ещё придумаете. Но при этом вы не обращаетесь к MyObject. Почему? Потому что он был не создан. Зачем вам обращаться к несуществующему объекту? Я имею ввиду, что вы просто не доходите до этого кода, например:

Код
// какой-то код
MyObject := TMyObject.Create('SavedGame01.dat');
// ещё какой-то код
MyObject.ShowOnScreen; // <- гарантировано <> nil, поэтому "if Assigned(MyObject) then" излишне 


Если создание объекта проваливается, то до использования объекта ниже вы не доходите. Именно поэтому я сказал, что ваши попытки сделать MyObJect := nil выглядят очень подозрительно. 

Как, в целом, узнают, что MyObJect <> nil? По месту выполнения кода.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 4.6.2010, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



CodeMonkey, благодарен безмерно. попробую Вам объяснить в чем штука со всеми нюансами.


Итак, у нас есть файл записей (record). Первая запись данного файла - это служебная информация прототипа. Доступ игрока к ней закрыт.

Остальные записи в файле это параметры реальных персонажей.

В классе будут ДВА конструктора CreateOpen и CreateNew.

Если игрок будет открывать уже созданного персонажа то вызываем конструктор CreateOpen, куда передадим лог-пасс.  CreateOpen будет проверять существование файла. Если нет, генерируем сообщение "Не хватает служебных ресурсов". Обваливаем конструктор исключением и  закрывем программу. Если файл есть, обходим его ночным дозором , поочередно забираем в переменные-поля параметры каждой записи и сравниваем их лог-пассы с лог-пассом введенным пользователем. Если совпадает то:

Грузим конструктором туда все данные из найденной записи. И создаем, наконец, объект. А если не совпадает: 

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

Второй конструктор CreatNew занимается другим. Он

Проверяет, существует ли файл. Если да, то берет служебную первую запись. Грузит значения в переменные. Берет лог-пасс введенный пользователем снова грузит в переменные (подменяя там формальные значения-умолчания взятые из служебной записи). и наконец создает вторую запись. 

Вторая запись - действительный персонаж. К нему впоследствии  обращается игрок.

 



Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 15:01


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 4.6.2010, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Ээээ.... ну? Что-то я не понял, что вы хотели сказать. 

Зачем тогда вам в этом сценарии обнуление переменной MyObject при неудаче? Если в обоих случаях при исключении вы просто игнорируете переменную и не обращаетесь к ней?

P.S. Конструктор не обязательно должен начинаться с Create. Удобно создать два конструктора так:
Код
type
  TMyObject = class
  ...
    constructor Create(...);
    constructor Open(...);
  end;

Ибо вызовы TMyObject.Create(...) и TMyObject.Open(...) смотрятся как-то "читабельнее", нежели TMyObject.CreateNew(...) и TMyObject.CreateOpen(...).

Это сообщение отредактировал(а) CodeMonkey - 4.6.2010, 14:48


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 4.6.2010, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



CodeMonkey, свершенно верно. В реальности в случае обрушения в конструкторе в указателе может остаться даже "мусор умолчания" (хотя по моему по умолчанию указатель равен - nil). Объекта то все равно нет и делать нам нечего.

 Но мусор для меня нежелателен, хочу чтоб все под контролем было .



Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 14:58


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
PsiMagistr
Дата 4.6.2010, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Вот еще какая тонкая штука, нюансик.

Код

//При закрытии глав. формы написал:

MyObject.Free;

//Ну это типа мы  создавали объекты, они успешно появлялись, а теперь закрываем прогу, гасим свет.



//Дескать баста, финита уходим, освободите память))).

//Но плюс к этому записал исключение в конструкторе (насчет того, что файл не найдется) а в кнопке его обработал:

procedure TForm1.Button1Click(Sender: TObject); //Кнопка

begin

MyObject:= nil;

try //Пытаюсь вызвать объект.

MyObJect:=TMyClass.Create('Проба.txt'); //Файла нет, создание объекта провалено. Вызывается деструктор!

Except

ShowMessage('Файл не найден!'); //Мол нет ресурсов, делать нечего. 

Form1.Close; //Уходим Обратите внимание на этот оператор.

end;
end;

{Допустим файл есть.  Если файл есть - объект есть. Работаем, при закрытии формы спокойно освобождаемся через MyObject.Free, А вдруг файла нет? Трах-бах - исключение в конструкторе. Деструктор пошел, ясное дело. Потом вызывается оператор Close. Но в обработчике Close записано //MyObject.Free. А объекта то в данном случае нет, деструктор уже вызвался.  

Не навредит ли этот MyObject.Free в данном случае У меня ошибок не выходит, но шут его знает как на самом деле

Кстати именно поэтому я хотел сделать вернуть в указатель - Nil при неудаче создания объекта. Тогда можно было бы написать при закрытии формы:}

If Object<>nil then MyObject.Free;


ДАННЫЙ ВОПРОС СНИМАЕТСЯ. Я голова садовая, совсем забыл, что Free контролирует указатель и только в случае указатель <> Nil вызывает деструктор.




Это сообщение отредактировал(а) bems - 4.6.2010, 17:49


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0853 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.