2 конструктора в одном классе

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

2 конструктора в одном классе

Сообщение Attid » 06.02.2007 12:59:21

В общем хочется сделать так :
Код: Выделить всё
  TDataFile = class(TObject)
  public
    constructor Create(const FileName: string);
    constructor Create(var FileStream: TStream);
    destructor Destroy; override;

чтоб было два конструктора в классе
возможно ли это и правельно ли так делать или лучше сделать отдельные классы ?
:?:
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение Alexander » 06.02.2007 14:25:24

А одинаковые имена принципиально ? Может задать разные ?

Или это эксперемент в смысле перегрузки функций ?
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 821
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Сообщение Sergei I. Gorelkin » 06.02.2007 14:38:26

Возможно ли это - да.

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

Например, в Вашем случае никто не мешает написать MyDataFile := TDataFile.Create; - при этом будет вызван конструктор TObject.Create и, очевидно, результат окажется не совсем тот, который ожидался.
Потом, если в конструкторе возникает исключение, то объект не создается. Это тоже может внести путаницу при последующем использовании кода...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Иван Шихалев » 07.02.2007 17:38:06

Sergei I. Gorelkin писал(а):Например, в Вашем случае никто не мешает написать MyDataFile := TDataFile.Create; - при этом будет вызван конструктор TObject.Create и, очевидно, результат окажется не совсем тот, который ожидался.

Насколько я помню, это не должно сработать.[/quote]
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Сообщение Sergei I. Gorelkin » 07.02.2007 18:22:58

Упс... Да, тут я прогнал немного. Вызов конструктора предка работает только в случае, когда потомок не имеет конструктора с таким же именем (но, тем не менее, работает, если потомок имеет конструктор с другим именем!)
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение MylnikovDm » 16.02.2007 22:48:40

чтоб было два конструктора в классе
возможно ли это и правельно ли так делать или лучше сделать отдельные классы?

Возможно ли - да, возможно. Вы можете объявить в своём классе любое количество конструкторов, а также деструкторов, если будет очень нужно. Но при объявлении деструкторовне забывайте, что автоматиески всегда будет вызываться виртуальный деструктор destroy, поскольку остальные классы из библиотеки знают только о нём.
Правильно ли - это вопрос сложный. Тут весь фокус в том, кто определяет правила. :)

Делать отдельные классы, если всё остальное совпадает - большого смысла не имеет, и вот это будет в некотором смысле неправильно. Любое дублирование кода (избыточность кода) начинает создавать проблемы, особенно когда проект разрастается.

Лично я в подобном случае сделал бы два конструктора с разными именами, но это зависит от стиля программирования. Кому-то, наоборот, больше по душе именно использования перегрузки методов.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Сообщение *vmr » 17.02.2007 15:59:23

В подобном случае я обычно делаю следующее:
Код: Выделить всё
TDataFile = class(TObject)
  protected
     Stream: TStream;
     procedure PreCreate; virtual;   // <-- должны переопределятся
     procedure PostCreate; virtual; // в классах-наследниках
  public
    constructor Create(const FileName: string); overload;
    constructor Create(var FileStream: TStream);  overload;
    destructor   Destroy; override;
  end;

  TPackedDataFile = class(TObject) // пример наследуемого класса
  protected
    EncodeStream: TEncodeStream;
    procedure PostCreate; override; // постинициализация
  public
    destructor   Destroy; override;
  end;

procedure TDataFile.PreCreate;
begin
  // BLAH BLAH BLAH
// Default settings
end;

procedure TDataFile.PostCreate;
begin
  // Do nothing
end;

constructor TDataFile.Create(const FileName: string);
begin
  PreCreate; // <--   !!!!
  Stream := TFileStream.Create(FileName, ...);
  NeedFreeStream := True;
  PostCreate; // <--   !!!!
end;

constructor TDataFile.Create(var FileStream: TStream);
begin
  PreCreate; // <--   !!!!
  Stream := FileStream;
  NeedFreeStream := False;
  PostCreate; // <--   !!!!
end;
//----------------
procedure TPackedDataFile.PostCreate;
begin
   // Все методы класса будут работать уже с TEncodeStream(через поле Stream).
   // Освобождать же оригинальный Stream будет TEncodeStream
   Stream := TEncodeStream.Create(Stream, NeedFreeStream);
   NeedFreeStream := True; // уничтожать поток на деструкторе
end;


PS: Сорри за громадный код :)
Аватара пользователя
*vmr
постоялец
 
Сообщения: 168
Зарегистрирован: 08.01.2007 01:46:07
Откуда: Киев

Сообщение Attid » 18.02.2007 17:40:39

*vmr
вот вместо бла бла просто глупое копирование файла на экран или преоброзование добавть и можно статейку на сайт
как раз 2 темы сразу 2 контсруктора + работа с наследием ;)
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru