Re[2]: Исключение в конструкторе + финализатор
От: 0x7be СССР  
Дата: 07.07.10 16:55
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Просто другая организация работы с памятью. Отсюда и другие правила поведения. В С++ правильно одно в силу стандарта С++ и ничего более. В дотнете и шарпе правильно своё в силу местных стандартов.

Я не ставил вопрос о соответствии реализации C# его спецификации
Я ставлю вопрос о том, насколько разумны отдельные положения этой спецификации.
Re[6]: Исключение в конструкторе + финализатор
От: 0x7be СССР  
Дата: 07.07.10 17:03
Оценка: +2
Здравствуйте, Mystic, Вы писали:


M>Ну смотри. Такой код смотрится красиво, но с ним будут проблемы:

Это, скажем прямо, не лучший стиль написания кода. И он по определению не exception-safe.
Лучше так:
  class test_t
  {
    private:
      std::auto_ptr<inner_test_t> test1;
      std::auto_ptr<inner_test_t> test2;
    public:
      test_t()
      {
        // Код, который может привести к исключению
        test1 = new inner_test_t();
        // Код, который может привести к исключению
        test2 = new inner_test_t(); 
        // Код, который может привести к исключению
      }  
  };


M>Поэтому приходится либо чрезмерно усложнять конструктор,

Где чрезмерное усложнение?

M>либо признать, что исключения в конструкторе штука стремная, и ее лучше инициализацию вынести в отдельный метод.

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

Вынос инициализации в отдельный метод — это вопрос отдельный и я его с исключениями никак не связываю.
Re[7]: Исключение в конструкторе + финализатор
От: hardcase Пират http://nemerle.org
Дата: 07.07.10 17:11
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Это, скажем прямо, не лучший стиль написания кода. И он по определению не exception-safe.

0>Лучше так:

Вот и для 99% классов код и будет аналогичным в C#.
Заострять внимание на финализаторе нужно только при работе с неуправляемыми ресурсами, о чем сразу же написал nikov.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[9]: Исключение в конструкторе + финализатор
От: Jack128  
Дата: 07.07.10 18:40
Оценка:
Здравствуйте, 0x7be, Вы писали:
>1. Создавать экземпляры абстрактных классов.
тут чисто техническая проблема. В дельфи на уровне компилятора просто невозможно запретить создание абстрактных классов, потому что там есть классовые ссылки..
Re[10]: Исключение в конструкторе + финализатор
От: 0x7be СССР  
Дата: 07.07.10 19:21
Оценка:
Здравствуйте, Jack128, Вы писали:

J>тут чисто техническая проблема. В дельфи на уровне компилятора просто невозможно запретить создание абстрактных классов, потому что там есть классовые ссылки..

Не понял. Классовая ссылка — это ссылка на экземпляр метакласса?
Чем это мешает запрещать создание экземпляров абстрактного класса?
В C# (а, точнее, в .net) тоже есть класс Type, который суть метакласс, но даже с его помощью такого не сделаешь.
При попытке динамически вызвать конструктор вылетит птич... исключение
Re[7]: Исключение в конструкторе + финализатор
От: Аноним  
Дата: 07.07.10 22:03
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Почему Вы считаете, что это неверный подход?


Да не то, чтобы неверный. Просто неоптимальный.
Про С спорить не буду, но в .net-е вы обязаны писать финализатор так, чтобы он был устойчив к повторному вызову и ошибкам внутри самого финализатора. От этого к финализатору, устойчивому к ошибкам инициализации — пол-шага. Т.е. он получается практически на халяву.

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

А вред-то где?
Re[3]: Исключение в конструкторе + финализатор
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 08.07.10 04:12
Оценка:
0x7be,

_FR>>Просто другая организация работы с памятью. Отсюда и другие правила поведения. В С++ правильно одно в силу стандарта С++ и ничего более. В дотнете и шарпе правильно своё в силу местных стандартов.

0>Я не ставил вопрос о соответствии реализации C# его спецификации
0>Я ставлю вопрос о том, насколько разумны отдельные положения этой спецификации.

За возможность вызвать виртуальный метод в конструкторе — моя личная благодарность создателям и особенно тов. Хейлсбергу

Как ты понимаешь, эта фича была бы невозможна, если бы термин "конструктор" в C# (или в CLR) семантически совпадал с термином "конструктор" в C++.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[7]: Исключение в конструкторе + финализатор
От: _FRED_ Черногория
Дата: 08.07.10 08:55
Оценка:
Здравствуйте, 0x7be, Вы писали:

А>>Короче — подсказываю — вам так кажется, потому что вы к этому привыкли. А на самом деле — в c++ тут допущена ошибка дизайна, которую подправили в .net.

0>Не согласен. Я считаю, что С++-ный подход вернее. Мои аргументы заключается в том, что тамошняя система в бОльшей степени сохраняет гарантии программисту относительно целостности объекта при вызове его методов (в т.ч. и деструктора). Это, кстати, относится и к возможности вызывать виртуальные методы в конструкторе.
0>Почему Вы считаете, что это неверный подход?

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

С какой стати файнализатор вообще должен вести себя как деструктор и с какой смысл имеет требование от него такого поведения

Это две совсем разные вещи, начиная с того, что предназначены для различных операций. Файнализатор — всего лишь место для освобождения неуправляемых ресурсов. С появлением SafeHandle-ов необходимость в них пропала совсем (если не принимать во внимание экзотические случаи).

Если в С++ деструктор является необходимым атрибутом большого количества объектов, то в шарпе это совсем не так.

Если заняться нечем, можно ещё порассуждать на тему того, чего это файнализаторы вызываются не как деструкторы в С++, а вообще в специальном отдельном потоке
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Исключение в конструкторе + финализатор
От: _FRED_ Черногория
Дата: 08.07.10 09:01
Оценка: 1 (1)
Здравствуйте, Mystic, Вы писали:

M>>>В C++ данные могут быть непроинициализированными. Почему деструктор никак не сможет установить, что конкретно было проинициализировано, а где просто мусор. Так что это вынужденная мера.

0>>С выделенным не согласен. Это очень логичное поведение, целиком укладывающееся в идею, что язык предоставляет программисту ряд инвариантов.

M>Ну смотри. Такой код смотрится красиво, но с ним будут проблемы:


Если код ниже — это С++, то нафига в деструкторе проверки на 0
M>      virtual ~test_t()
M>      {
M>        delete test1;
M>        delete test2;
M>      }


M>Поэтому приходится либо чрезмерно усложнять конструктор,


Те проблемы, о которых ты говоришь, к С++ имеют весьма опосредованное значение, ибо в С++ помимо сишных указателей есть и более умные

M>либо признать, что исключения в конструкторе штука стремная, и ее лучше инициализацию вынести в отдельный метод.


Исключение в конструкторе — штука более чем ясная.

M>Собственно говоря, ради возможности такой удобной записи все и затеяно начиная с Delphi.


Можно увидеть пруфлинк?
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Исключение в конструкторе + финализатор
От: _FRED_ Черногория
Дата: 08.07.10 09:04
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

_FR>>>Просто другая организация работы с памятью. Отсюда и другие правила поведения. В С++ правильно одно в силу стандарта С++ и ничего более. В дотнете и шарпе правильно своё в силу местных стандартов.

0>>Я не ставил вопрос о соответствии реализации C# его спецификации
0>>Я ставлю вопрос о том, насколько разумны отдельные положения этой спецификации.

LCR>За возможность вызвать виртуальный метод в конструкторе — моя личная благодарность создателям и особенно тов. Хейлсбергу


Тут вот я не согласен: оченьо неожиданные спец-эффекты бывают Нафик-нафик такие пироги. Ничего хорошего, "рождённого" из этой фичи, я ещё не видел и представить даже не могу. Может, покажешь?

LCR>Как ты понимаешь, эта фича была бы невозможна, если бы термин "конструктор" в C# (или в CLR) семантически совпадал с термином "конструктор" в C++.


+1.
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Исключение в конструкторе + финализатор
От: 0x7be СССР  
Дата: 08.07.10 09:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Если заняться нечем, можно ещё порассуждать на тему того, чего это файнализаторы вызываются не как деструкторы в С++, а вообще в специальном отдельном потоке

Ну это как раз не большая загадка
В целом мне твой поинт понятен.
Re[8]: Исключение в конструкторе + финализатор
От: blackhearted Украина  
Дата: 08.07.10 09:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 0x7be, Вы писали:


0>>Почему Вы считаете, что это неверный подход?


А>Да не то, чтобы неверный. Просто неоптимальный.

А>Про С спорить не буду, но в .net-е вы обязаны писать финализатор так, чтобы он был устойчив к повторному вызову и ошибкам внутри самого финализатора. От этого к финализатору, устойчивому к ошибкам инициализации — пол-шага. Т.е. он получается практически на халяву.

Речь не про С, а про С++.
Re[7]: Исключение в конструкторе + финализатор
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 08.07.10 09:37
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Здравствуйте, Mystic, Вы писали:



M>>Ну смотри. Такой код смотрится красиво, но с ним будут проблемы:

0>Это, скажем прямо, не лучший стиль написания кода. И он по определению не exception-safe.
0>Лучше так:

Это я понимаю, это просто иллюстрация основной идеи. Более реальный пример, например, открытие файла. Создание какого-нить объекта ядра. Память была просто в качестве примера некоторого ресурса, поэтому я так и писал код. Замени test1 и test2 на что-нить вроде

  _file = open(filepath.c_str(), O_RDONLY);
  if (_file < 0) throw e();

  if (fstat(_file, &stat_buf) < 0) throw e(); // close(_file); 
  _size = stat_buf.st_size;

  _memory = mmap(0, _size, PROT_READ, MAP_PRIVATE, _file, 0);
  if (_memory == NULL || _memory == MAP_FAILED) throw e(); // close(_file)

  // Продолжаем инициализацию объекта


0>Если не иметь навыков работы с исключениями, то они в принципе станут штукой стрёмной. Exception-unsafe-код можно написать везде. Некоторые, кстати, принципиально отказываются от механизма исключений и имеют на это право. Но если с уметь с исключениями работать, то исключения в конструкторе становятся не более стремными, чем в любом другом месте программы.


Чисто субъективно, в том же Delphi проще. Как раз из-за автоматического вызова деструктора и автоматической инициализации.
Re[7]: Исключение в конструкторе + финализатор
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 08.07.10 09:43
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Те проблемы, о которых ты говоришь, к С++ имеют весьма опосредованное значение, ибо в С++ помимо сишных указателей есть и более умные


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

M>>Собственно говоря, ради возможности такой удобной записи все и затеяно начиная с Delphi.


_FR> Можно увидеть пруфлинк?


constructor TClass.Create();
begin
  inherited;

  FFile1 := CreateFile(...);
  Check(FFile1 <> INVALID_HANDLE_VALUE, 'CreateFile fails');

  FFile2 := CreateFile(...);
  Check(FFile2 <> INVALID_HANDLE_VALUE, 'CreateFile fails');
end;  

destructor TClass.Destroy();
begin
  if IsValid(FFile1) then CloseHandle(FFile1);
  if IsValid(FFile2) then CloseHandle(FFile2);
  inherited;
end;
Re[9]: Исключение в конструкторе + финализатор
От: Аноним  
Дата: 08.07.10 09:44
Оценка:
Здравствуйте, blackhearted, Вы писали:
B>Речь не про С, а про С++.
Вах! Ну надо же! Ну кто бы мог подумать!
P.S. У меня на ноуте кнопочку + лежа нажимать неудобно.
Re[8]: Исключение в конструкторе + финализатор
От: _FRED_ Черногория
Дата: 08.07.10 09:55
Оценка:
Здравствуйте, Mystic, Вы писали:

_FR>>Те проблемы, о которых ты говоришь, к С++ имеют весьма опосредованное значение, ибо в С++ помимо сишных указателей есть и более умные

M>Не во всех языках живут шаблоны. Плюс память это не единственный ресурс

При чём здесь другие языки? Речь конкретно о С++.

M>>>Собственно говоря, ради возможности такой удобной записи все и затеяно начиная с Delphi.


_FR>> Можно увидеть пруфлинк?


M>constructor TClass.Create();


Мне интересно взглянуть на подтверждение того, что "затеяно" именно "ради возможности такой удобной записи".

P.S. Неужели менее уродским способом нельзя в дельфях то же самое написать?
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Исключение в конструкторе + финализатор
От: hardcase Пират http://nemerle.org
Дата: 08.07.10 10:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>P.S. Неужели менее уродским способом нельзя в дельфях то же самое написать?


Можно. Надо только TFileStream использовать.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: Исключение в конструкторе + финализатор
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 08.07.10 10:22
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тут вот я не согласен: оченьо неожиданные спец-эффекты бывают Нафик-нафик такие пироги. Ничего хорошего, "рождённого" из этой фичи, я ещё не видел и представить даже не могу. Может, покажешь?


Например, в VCL при вызове конструктора формы в конце концов вызовется метод виртуальный CreateParams, в котором можно будет настроить параметры вызовов RegisterClass и CreateWindow.
Re[10]: Исключение в конструкторе + финализатор
От: _FRED_ Черногория
Дата: 08.07.10 10:24
Оценка:
Здравствуйте, hardcase, Вы писали:

_FR>>P.S. Неужели менее уродским способом нельзя в дельфях то же самое написать?


H>Можно. Надо только TFileStream использовать.


Ага, мне тоже показалось странным, что в дельфях нету нормальной (здесь: бросающей исключения) обёртки над CreateFile.

Тогда, что бы придать нормальности тому коду, не хватает только метода, принимающего объект, проверяющего — не nil (так, кажется?) ли он и вызывающей какой-нить Close() или Dispose().
Help will always be given at Hogwarts to those who ask for it.
Re[11]: Исключение в конструкторе + финализатор
От: hardcase Пират http://nemerle.org
Дата: 08.07.10 10:26
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тогда, что бы придать нормальности тому коду, не хватает только метода, принимающего объект, проверяющего — не nil (так, кажется?) ли он и вызывающей какой-нить Close() или Dispose().


FreeAndNil(FFile);


Где FFile это поле. Процедура грохнет объект если он не равен nil и занулит ссылку.
/* иЗвиНите зА неРовнЫй поЧерК */
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.