паттерн "Мюнхгаузен"
От: Rostislav_Pro  
Дата: 02.09.09 10:17
Оценка: 1 (1) :))) :))) :))) :))) :))) :))) :)
Один мега-программист из нашей конторы весьма оригинально использовал исключения в C++:

if(somethingBad)
{
  FatalException();
  //вместо throw FatalException();
}


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

class FatalException
{
public:
  FatalException()
  {
    throw *this; // :)
  }
};


Теперь одинаково работают (в VS 2005) оба варианта:

if(somethingBad)
  throw FatalException();

if(somethingBad)
  FatalException();


А может кто-нибудь уже встречал такое самобросающееся исключение??


02.09.09 20:31: Перенесено модератором из 'Коллеги, улыбнитесь' — Кодт
02.09.09 20:31: Перенесено модератором из 'Коллеги, улыбнитесь' — Кодт
Re: паттерн "Мюнхгаузен"
От: Мурлакотам Россия  
Дата: 02.09.09 10:52
Оценка:
if(somethingBad)
{
  FatalException();
  //вместо throw FatalException();
}


=>

class FatalException
{
public:
  FatalException()
  {
    throw *this; // :)
  }
};


Вполне грамотный рефакторинг. Без вмешательства в код, использующий FatalException(), удалось добиться ожидаемого поведения предельно малой кровью. Но
throw *this;
конечно, улыбает, чего уж
Re[2]: паттерн "Мюнхгаузен"
От: midcyber
Дата: 02.09.09 11:23
Оценка: +1
Здравствуйте, Мурлакотам, Вы писали:

М>Вполне грамотный рефакторинг. Без вмешательства в код, использующий FatalException(), удалось добиться ожидаемого поведения предельно малой кровью.


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

Кстати, я не знаю C++, это нормально, кидать исключение в конструкторе, да еще отдавая указатель на недосозданный объект? ;)
Re: паттерн "Мюнхгаузен"
От: rus blood Россия  
Дата: 02.09.09 11:37
Оценка: :)
Здравствуйте, Rostislav_Pro, Вы писали:

Интересно, а если добавить конструктор копии с такой же реализацией ???
Имею скафандр — готов путешествовать!
Re[3]: паттерн "Мюнхгаузен"
От: Vzhyk  
Дата: 02.09.09 11:53
Оценка:
midcyber пишет:
>
> По-моему, это ужасно.
Селяви.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: паттерн "Мюнхгаузен"
От: alzt  
Дата: 02.09.09 11:55
Оценка: +2
Здравствуйте, midcyber, Вы писали:

М>>Вполне грамотный рефакторинг. Без вмешательства в код, использующий FatalException(), удалось добиться ожидаемого поведения предельно малой кровью.


M>По-моему, это ужасно.

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

M>Кстати, я не знаю C++, это нормально, кидать исключение в конструкторе, да еще отдавая указатель на недосозданный объект?


Кидать нормально.
Там не отдаётся указатель. *this — это сам объект, т.е. исключение кидается по значению.
Re[3]: паттерн "Мюнхгаузен"
От: Rostislav_Pro  
Дата: 02.09.09 12:04
Оценка:
Здравствуйте, midcyber, Вы писали:

M>Здравствуйте, Мурлакотам, Вы писали:


М>>Вполне грамотный рефакторинг. Без вмешательства в код, использующий FatalException(), удалось добиться ожидаемого поведения предельно малой кровью.


M>По-моему, это ужасно.

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

M>Кстати, я не знаю C++, это нормально, кидать исключение в конструкторе, да еще отдавая указатель на недосозданный объект?


Недосозданности конечно можно избежать, если кидать новый объект, созданный специальным приватным конструктором, который не генерит исключений. Но тогда пропадет вся соль метода — "throw *this"
Re[2]: паттерн "Мюнхгаузен"
От: Rostislav_Pro  
Дата: 02.09.09 12:05
Оценка:
Здравствуйте, rus blood, Вы писали:

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


RB>Интересно, а если добавить конструктор копии с такой же реализацией ???


Наверно стек ляжет. А по хорошему, конструктор копий надо сделать, но чтобы исключений не бросал.
Re: паттерн "Мюнхгаузен"
От: Vamp Россия  
Дата: 02.09.09 16:35
Оценка: 1 (1) +1
Плохое решение. Во-первых, возвращается недосозданный объект. Во-вторых, теряется контекст исключения.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: паттерн "Мюнхгаузен"
От: Кодт Россия  
Дата: 02.09.09 16:36
Оценка: -1
Здравствуйте, alzt, Вы писали:

A>Там не отдаётся указатель. *this — это сам объект, т.е. исключение кидается по значению.

... и происходит срезка!
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[2]: паттерн "Мюнхгаузен"
От: Alexander G Украина  
Дата: 02.09.09 16:59
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Интересно, а если добавить конструктор копии с такой же реализацией ???


Стандарт требует чтобы не бросал, поэтому боюсь, будет что-то ужасное.
Русский военный корабль идёт ко дну!
Re[5]: паттерн "Мюнхгаузен"
От: Alexander G Украина  
Дата: 02.09.09 17:01
Оценка: :))) :))
Здравствуйте, Кодт, Вы писали:

A>>Там не отдаётся указатель. *this — это сам объект, т.е. исключение кидается по значению.

К>... и происходит срезка!

А если из деструктора бросать, срезки не будет!
Русский военный корабль идёт ко дну!
Re[6]: паттерн "Мюнхгаузен"
От: Кодт Россия  
Дата: 02.09.09 17:47
Оценка: +1 :))) :))) :))
Здравствуйте, Alexander G, Вы писали:

A>>>Там не отдаётся указатель. *this — это сам объект, т.е. исключение кидается по значению.

К>>... и происходит срезка!

AG>А если из деструктора бросать, срезки не будет!

Из деструктора можно не заморачиваться с throw *this, а тупо писать там terminate(). Ибо, чего уж.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re: паттерн "Мюнхгаузен"
От: Sergey Россия  
Дата: 02.09.09 19:21
Оценка:
Здравствуйте, Rostislav_Pro, Вы писали:

R_P>Один мега-программист из нашей конторы весьма оригинально использовал исключения в C++:


R_P>
R_P>if(somethingBad)
R_P>{
R_P>  FatalException();
R_P>  //вместо throw FatalException();
R_P>}
R_P>


R_P>В связи с этим был придуман (чисто чтоб поржать) подход, позволяющий исправить кривизну его рук:


R_P>
R_P>class FatalException
R_P>{
R_P>public:
R_P>  FatalException()
R_P>  {
R_P>    throw *this; // :)
R_P>  }
R_P>};
R_P>


А чё не
void FatalException()
{
    throw Alles();
}

?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[2]: паттерн "Мюнхгаузен"
От: Alexander G Украина  
Дата: 02.09.09 20:46
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Плохое решение. Во-первых, возвращается недосозданный объект. Во-вторых, теряется контекст исключения.


Ну если throw в финальном по иерархии классе, и после инициализации, то как бы ничего плохого не произойдёт. Конструктор копирования скопирует контекст, для исключений он обязан существовать, работать и не бросать.
Русский военный корабль идёт ко дну!
Re[5]: паттерн "Мюнхгаузен"
От: Erop Россия  
Дата: 03.09.09 05:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>... и происходит срезка!

Откуда тут срезка-то? Всё, что более выведенное ещё не сконструировалось!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: паттерн "Мюнхгаузен"
От: Erop Россия  
Дата: 03.09.09 05:17
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>А если из деструктора бросать, срезки не будет!


Во-первых, будет примерно такая же "срезка", как и в случае с конструктором. Так как всё более выведенное к моменту вызова деструктора уже разрушится.

Во-вторых, не будет работать по любому. Так как деструктор, в отличии от конструктора, всего один. Например он будет зваться и для копий объекта...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: паттерн "Мюнхгаузен"
От: Alexander G Украина  
Дата: 03.09.09 06:07
Оценка: -1
Здравствуйте, Erop, Вы писали:

E>Во-первых, будет примерно такая же "срезка", как и в случае с конструктором. Так как всё более выведенное к моменту вызова деструктора уже разрушится.


Во-первых, насколько я понял, речь идёт о такой срезке:


struct printer_error
{
  explicit printer_error(int handle = 0)
  {
    mHandle = handle ;
    throw* this;
  }
};

struct out_of_ink : printer_error
{
public:
  explicit out_of_ink(int handle = 0) : printer_error(handle)
  {
    throw* this;
  }
};


out_of_ink(); // бросит printer_error. но mHandle будет правильным.


Соответсвенно, для деструктора такой срезки не будет.

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


Во-вторых, не думаю, что кто-то всерьёз воспримет моё сообщение
Русский военный корабль идёт ко дну!
Re[4]: паттерн "Мюнхгаузен"
От: jazzer Россия Skype: enerjazzer
Дата: 03.09.09 06:14
Оценка:
Здравствуйте, alzt, Вы писали:

M>>Кстати, я не знаю C++, это нормально, кидать исключение в конструкторе, да еще отдавая указатель на недосозданный объект?


A>Кидать нормально.

A>Там не отдаётся указатель. *this — это сам объект, т.е. исключение кидается по значению.

по какому значению, если объект не сконструирован?
Тут позовется конструктор копирования, у которого в параметре будет ссылка, указывающая на несуществующий объект — UB при попытке использования.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: паттерн "Мюнхгаузен"
От: Rostislav_Pro  
Дата: 03.09.09 06:28
Оценка:
S>А чё не
S>
S>void FatalException()
S>{
S>    throw Alles();
S>}
S>

S>?

Тогда уж лучше throw Alles::Kaput(). А еще можно так:

class FatalException
{
public:
  FatalException(bool doThrow = true)
  {
    if(doThrow)
      throw FatalException(false);
  }
};


Или так:

class FatalException
{
public:
  FatalException()
  {
      throw FatalException(NoThrow());
  }
private:
  struct NoThrow{};
  FatalException(NoThrow)
  {
  }
};


В обоих случаях избавляемся от UB при копировании из несозданного объекта
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.