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

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

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

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

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

Сообщение Attid »

В общем хочется сделать так :

Код: Выделить всё

  TDataFile = class(TObject)
  public
    constructor Create(const FileName: string);
    constructor Create(var FileStream: TStream);
    destructor Destroy; override;

чтоб было два конструктора в классе
возможно ли это и правельно ли так делать или лучше сделать отдельные классы ?
:?:
Аватара пользователя
Alexander
энтузиаст
Сообщения: 888
Зарегистрирован: 18.12.2005 18:10:00
Откуда: оттуда
Контактная информация:

Сообщение Alexander »

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

Или это эксперемент в смысле перегрузки функций ?
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

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

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

Например, в Вашем случае никто не мешает написать MyDataFile := TDataFile.Create; - при этом будет вызван конструктор TObject.Create и, очевидно, результат окажется не совсем тот, который ожидался.
Потом, если в конструкторе возникает исключение, то объект не создается. Это тоже может внести путаницу при последующем использовании кода...
Аватара пользователя
Иван Шихалев
энтузиаст
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург
Контактная информация:

Сообщение Иван Шихалев »

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

Насколько я помню, это не должно сработать.[/quote]
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Упс... Да, тут я прогнал немного. Вызов конструктора предка работает только в случае, когда потомок не имеет конструктора с таким же именем (но, тем не менее, работает, если потомок имеет конструктор с другим именем!)
MylnikovDm
постоялец
Сообщения: 103
Зарегистрирован: 15.02.2007 20:26:10
Откуда: Челябинск

Сообщение MylnikovDm »

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

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

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

Лично я в подобном случае сделал бы два конструктора с разными именами, но это зависит от стиля программирования. Кому-то, наоборот, больше по душе именно использования перегрузки методов.
Аватара пользователя
*vmr
постоялец
Сообщения: 168
Зарегистрирован: 08.01.2007 00:46:07
Откуда: Киев
Контактная информация:

Сообщение *vmr »

В подобном случае я обычно делаю следующее:

Код: Выделить всё

 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: Сорри за громадный код :)
Аватара пользователя
Attid
долгожитель
Сообщения: 2589
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

*vmr
вот вместо бла бла просто глупое копирование файла на экран или преоброзование добавть и можно статейку на сайт
как раз 2 темы сразу 2 контсруктора + работа с наследием ;)
Ответить