-
1. Data: 2010-09-15 17:39:18
Temat: Zagwozdka - wyjątek w konstruktorze?
Od: "Wojciech \"Spook\" Sura" <spook"mad@hatter"op.pl>
Witam!
Zaprojektowałem kilka klas, które będą przechowywały dane liczbowe różnych
typów (liczba całkowita, zmiennoprzecinkowa, macierz itp.) Jedną z nich
jest ułamek zwykły, któremu w konstruktorze przekazywany jest licznik i
mianownik. I tu rodzi się problem:
CIntFraction::CIntFraction(int Anumerator, int Adenominator)
{
if (Adenominator == 0)
// I co teraz?...
}
Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem. Mogę też
zaakceptować licznik i mianownik w takiej postaci, w jakiej je dostanę, a
wyjątkiem rzucić dopiero podczas próby dobrania się do wartości ułamka,
ale przez jakiś czas będzie on wisieć w pamięci z nieprawidłowymi danymi,
co również mi się nie podoba.
Jak wybrnąć z tej sytuacji?
Pozdrawiam -- Spook.
--
! ._______. Warning: Lucida Console sig! //) !
! || spk || www.spook.freshsite.pl / _ """*!
! ||_____|| spook at op.pl / ' | ""!
! | ___ | tlen: spoko_ws gg:1290136 /. __/"\ '!
! |_|[]_|_| May the SOURCE be with you! \/) \ !
-
2. Data: 2010-09-15 18:53:10
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Sebastian Biały <h...@p...onet.pl>
On 2010-09-15 19:39, Wojciech "Spook" Sura wrote:
> Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
> wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem.
To zrób fabrykę tego obiektu i rzucaj z niej.
-
3. Data: 2010-09-15 19:06:58
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Bronek Kozicki <b...@s...net>
On 15/09/2010 18:39, Wojciech "Spook" Sura wrote:
> Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
> wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem.
Dlaczego nie? lepiej w konstruktorze niż w innej funkcji.
B.
-
4. Data: 2010-09-15 20:28:37
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: Tomasz Sowa <t...@t...NOSPAM.org>
Dnia Wed, 15 Sep 2010 19:39:18 +0200, Wojciech "Spook" Sura napisał(a):
> Jak wybrnąć z tej sytuacji?
Ustaw dodatkową flagę NaN (not a number). Przyda się także podczas innych
operacji np dzielenia.
--
Tomek
-
5. Data: 2010-09-15 23:10:54
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: klops <k...@k...pl>
Odpowiadam, bo dotychczasowe odpowiedzi są raczej słabe...
Gdy rzucasz wyjątek w konstruktorze, to:
1. Zmienne utworzone na stosie zostaną prawidłowo zlikwidowane.
2. Zmienne utworzone na stercie (new) nie zostaną usunięte.
Aby zaradzić 2. należy używać inteligentnych wkaźników (lub czegoś
podobnego) tworzonych na stosie, np. auto_ptr.
-
6. Data: 2010-09-16 07:19:01
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: klops <k...@k...pl>
W dniu 2010-09-16 18:24, Michoo pisze:
> W dniu 16.09.2010 01:10, klops pisze:
>> Odpowiadam, bo dotychczasowe odpowiedzi są raczej słabe...
>>
>> Gdy rzucasz wyjątek w konstruktorze, to:
>> 1. Zmienne utworzone na stosie zostaną prawidłowo zlikwidowane.
>> 2. Zmienne utworzone na stercie (new) nie zostaną usunięte.
>>
>> Aby zaradzić 2. należy używać inteligentnych wkaźników (lub czegoś
>> podobnego) tworzonych na stosie, np. auto_ptr.
> Dlaczego okłamujesz Wojciecha? (No chyba że to zwykła ignorancja a nie
> zła wola? Ale lansowaleś się na kogoś mającego pojęcie o języku...)
Masz rację, że lansuję się tu na max. Więc nie mogłem obejść twego postu
obojętnie...
Wracając do tematu, zastanów się nad tym (może bozia pozwoli dostrzec
problem o którym wzmiankowałem...):
#include <iostream>
using namespace std;
char tab[100];
struct Bar{
Bar(){cout <<"Bar"<<endl;}
~Bar(){cout <<"~Bar"<<endl;}
};
class Foo{
Bar* b;
public:
Foo()
{
b = new Bar();
cout <<"Foo"<<endl;
throw 1;
}
~Foo()
{
delete b;
cout <<"~Foo"<<endl;
}
static void * operator new (size_t size)
{
cout <<"new"<<endl;
return (Foo*)tab;
}
static void operator delete (void *p, size_t size)
{
cout <<"delete"<<endl;
}
};
main()
{
try{
Foo *f=new Foo();
}
catch(...){
cout <<"catch"<<endl;
}
}
>trhow.exe
new
Bar
Foo
delete
catch
Dla podpowiedzi: b wyciekło...
-
7. Data: 2010-09-16 08:07:30
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: "Wojciech \"Spook\" Sura" <spook"mad@hatter"op.pl>
Dnia 15-09-2010 o 21:06:58 Bronek Kozicki <b...@s...net> napisał(a):
> On 15/09/2010 18:39, Wojciech "Spook" Sura wrote:
>
>> Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
>> wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem.
>
> Dlaczego nie? lepiej w konstruktorze niż w innej funkcji.
Ok, a co stanie się wówczas z połowicznie zainicjowanym obiektem? Jeśli
konstruktor rzuci wyjątkiem, nie wykona się przypisanie do zmiennej
wskaźnikowej - czyli w pamięci pozostanie zaalokowany (choć nie do końca
zainicjowany) obiekt.
> B.
Pozdrawiam -- Spook.
--
! ._______. Warning: Lucida Console sig! //) !
! || spk || www.spook.freshsite.pl / _ """*!
! ||_____|| spook at op.pl / ' | ""!
! | ___ | tlen: spoko_ws gg:1290136 /. __/"\ '!
! |_|[]_|_| May the SOURCE be with you! \/) \ !
-
8. Data: 2010-09-16 11:28:50
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: badzio <b...@g...com>
On 15 Wrz, 19:39, "Wojciech \"Spook\" Sura" <spook"mad@hatter"op.pl>
wrote:
> Mogę oczywiście rzucić wyjątkiem, ale - z tego, co wiem - rzucanie
> wyjątkami w konstruktorze jest nieszczególnie radosnym pomysłem.
W symbianie jest cos takiego jak konstruktor dwufazowy. Konstruktor
niech bedzie prywatny, zrob takze prywatna metoda inicjalizujaca
(zgodnie z konwencja symbiana: ConstructL) oraz statyczna, publiczna
metode do tworzenia obiektow (NewL). Metoda inicjalizujaca rzuca
wyjatek. Mozesz go obsluzyc w NewL i zwrocic nulla (niszczac przy tym
dopiero co stworzony obiekt) lub przekazac 'wyzej'.
-
9. Data: 2010-09-16 12:22:48
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: "Marcin 'Qrczak' Kowalczyk" <q...@k...org.pl>
On Sep 16, 10:07 am, "Wojciech \"Spook\" Sura"
<spook"mad@hatter"op.pl> wrote:
> > Dlaczego nie? lepiej w konstruktorze niż w innej funkcji.
>
> Ok, a co stanie się wówczas z połowicznie zainicjowanym obiektem?
Zależy od tego, w którym momencie zostanie rzucony wyjątek. Tym polom,
które zostały już skonstruowane, zostanie zawołany destruktor. Tym,
które nie -- nie.
Jeśli konstruktor został wołany przy okazji new, to zostanie wykonane
odpowiadające mu delete.
O resztę musi zadbać programista.
-
10. Data: 2010-09-16 15:46:36
Temat: Re: Zagwozdka - wyjątek w konstruktorze?
Od: klops <k...@k...pl>
> Standardowym podejściem w sytuacji gdy używamy "gołych" wskaźników i
> wyjątków w jednym miejscu (nie tylko w konstruktorze) jest taki zapis:
Jest coś takiego jak "zdobywanie zasobów jest inicjowaniem" i auto_ptr
wspiera tą technikę. Prawidłowe rozwiązanie tego problemu jest takie:
#include <iostream>
#include <memory>
using namespace std;
char tab[100];
struct Bar{
Bar(){cout <<"Bar"<<endl;}
~Bar(){cout <<"~Bar"<<endl;}
};
class Foo{
auto_ptr<Bar> b;
public:
Foo()
{
b.reset(new Bar());
cout <<"Foo"<<endl;
throw 1;
}
~Foo()
{
cout <<"~Foo"<<endl;
}
static void * operator new (size_t size)
{
cout <<"new"<<endl;
return (Foo*)tab;
}
static void operator delete (void *p, size_t size)
{
cout <<"delete"<<endl;
}
};
main()
{
try{
Foo *f=new Foo();
}
catch(...){
cout <<"catch"<<endl;
}
}
>throw.exe
new
Bar
Foo
~Bar
delete
catch