c++ wyjątki

0

Hey,
Tak więc mam taki problem: Nie za bardzo rozumiem wyjątki...
Jak to działa ?

 
klasa::klasa()
{
    try 
          {
            plik.open("............txt", ios::in | ios::out);
            if( plik.good() == true )
            {
                "Uzyskano dostep do pliku!" ;
            } else "Dostep do pliku zostal zabroniony!";
          }
          catch(OpenError)
          {
             
          }
    
}

chodzi mi o to, że chce napisac konstruktor który otwiera sobie plik ale jezeli go nie otworzy to chce by zwrócił wyjątek tam coś wykona i potem kolejna próba otwarcia itp itd
no i problem w tym, że nie rozumiem za bardzo jak to zrobić ponieważ:
nie ogarniam tutaj bloku try i kiedy stosuje throw
jest troche inaczej niż w pythonie bo.
No nie rozumiem mógł by mi ktoś wytłumaczyć ? Jak to działa i wgl ?
Bo czytałem o tym i dalej nie mam pojęcia jak zrobić to co sobie wymyśliłem. :(

2

klasy standardowej biblioteki dziedzicza z base_exception , poczytaj w referencji o wyjatkach
w klasie po ktorej dziedziczy fstream
http://cplusplus.com/reference/iostream/ios/exceptions/
i o jego budowie
http://cplusplus.com/reference/iostream/fstream/

gdzies chyba slyszalem ze nie powinno sie stosowac wyjatkow wewnatrz konstruktorow i destruktorow ale moze ktos lepiej sie znajacy odpowie ci dokladnie


peace
ChS

0

Co do używania mechanizmu wyjątków w konstruktorach i destruktorach to wydaje mi sie, ze chodzi o to, zeby wyjatek nie był rzucany poza konstruktor/destruktor tylko łapany wewnątrz i tam byłaby odpowiednia reakcja na dany błąd.

0

Wyrzucanie wyjątku z destruktora jest niebezpieczne i nie powinno się tego nigdy robić. Problem pojawia się, kiedy do wyrzucenia wyjątku z destruktora dojdzie podczas "odwijania stosu" po wyrzuceniu innego wyjątku. Który wyjątek miałby być wtedy obsłużony? Standard mówi, że w takim wypadku należy wywołać terminate(), które zasadniczo ubije nam program.

Z konstruktorami jest inaczej. Konstruktor może wyrzucić wyjątek i nic strasznego się nie stanie. Jednak destruktor nie zostanie wywołany. Oznacza to, że jeżeli alokowano jakieś zasoby przed wyrzuceniem wyjątku to nie zostaną one zwolnione. Na tę okazję wymyślono technikę RAII.

0

W konstruktorach można spokojnie używać wyjątków.
W destruktorach kategorycznie nie wolno, jako że mogą prowadzić do katastrofy przy próbie odwikłania stosu. Przykład:

#include <iostream>
using namespace std;

class Test {
public:
    Test() {
        cout << "Test()" << endl;
    }

    void f() {
        cout << "f(), throwing 5..." << endl;
        throw 5;
    }

    ~Test() {
        cout << "~Test(), throwing 3..." << endl;
        throw 3;
    }
};

int main() {
    try {
        Test t;
        t.f();
    } catch (...)  {
        cout << "To sie nie wykona." << endl;
    }

    return 0;
}
0

Rzucanie wyjątków w konstruktorze też nie jest dobrym pomysłem, bo gdy konstruktor nie wykona się do końca to potem nie zostanie wywołany dla niego destruktor, wiec jest prawdopodobieństwo wystąpienia memory leaka.

#include <iostream>
using namespace std;
 
class Test {
public:
    static int i ;
 
   Test() {
     objid = i++;
     cout << "Test() " << objid << endl;
     if(i == 3) throw 3;
    }
 ~Test() {
     cout << "~Test()" << objid << endl;
   }
 int objid;
};

int Test::i = 0;

int main() {
    try {
        Test t[5];
    } catch (int i)  {
        cout << "catch " << i << endl;
    }
 return 0;
}

Output:

Test() 0
Test() 1
Test() 2
~Test()1
~Test()0
catch 3 

@up del sry

0

myhm, no to dobrze uslyszalem, dalej jednak nie uzywam wyjatkow.
Do tej pory tworze klasy ktore maja okreslone stany na bool albo na maskach stanu, jak uwazacie lepsze jest takie rozwiazanie konstrukcji klas:
class klasa_bez_wyjatkow{
enum stan_{ 1, 2 };
bool stan[1];
bool funkcjaPlikowa(); // zakladam udana operacja stan[0]=true;
bool funkcjaModyfikujaca();//zakladam udana modyfikacje stan[1]=true;
void set_state(unsigned s_) stan[s_]=true;
void get_state() ...
void unset_state() ...
};

czy moze konstrukcja z wyjatkami

class klasa_z_wyjatkami{
void funkcjaPlikowa(); // zakladam ze wewnatrz zostanie wyrzucony blad operacji na pliku
void funkcjaModyfikujaca(); // zakldam ze gdy modyfikacja nie zostanie wykonana wyrzucony blad operacji
}
int main(){
klasa_bez_wyjatkow klasa_bez;
klasa_z_wyjatkami klasa_z;
klasa_bez.setState(klasa_bez.stan[klasa_bez.stan_.1]);
// po sprawdzeniu stanu po jednej iteracji w watku jadra programu wiem ze jest blad

//tutaj zaczyna sie watek iterujacy sprawdzanie stanu jadra
try{ klasa_z.funkcjaPlikowa() }
catch{ exception }
{
//po wychwyceniu wyjatku po kolejnej iteracji w watku jadra programu wiem ze jest blad
}
//tutaj konczy sie watek iterujacy sprawdzanie stanu jadra
}

no i tutaj biore pod uwage ze w programie jest jadro ktore wlasnie utrzymuje stan i dzieki temu steruje GUI (wyswietlam aktualnie porzadany stan) , oraz obiektami ktore odbieraja rezultaty z GUI ( oczywiscie obiekty maja wlasne stany i GUI ma tez wlasne stany ).

  1. Czy stosowanie tej techniki sprawdzania stanu aplikacji bez wyjatkow to dobre podejscie tworzenia architektury do programu?
  2. Czy uzywanie wyjatkow bez uzywania stanu to dobre podejscie? ( no dobra tego nie umiem nawet sobie wyobrazic )
  3. To w takim razie w jakich sytuacjach jest przydatne uzywanie wyjatkow.

peace
ChS

0
00001010 napisał(a):
  1. Czy stosowanie tej techniki sprawdzania stanu aplikacji bez wyjatkow to dobre podejscie tworzenia architektury do programu?
  2. Czy uzywanie wyjatkow bez uzywania stanu to dobre podejscie? ( no dobra tego nie umiem nawet sobie wyobrazic )
  3. To w takim razie w jakich sytuacjach jest przydatne uzywanie wyjatkow.
  1. Nie
  2. Powinienes stosowac i to, i to (o ile jest taka potrzeba).
  3. Zawsze, po to, zeby nie doprowadzic do niezaplanowanego zakonczenia aplikacji, wyciekow pamieci itd.

1 użytkowników online, w tym zalogowanych: 0, gości: 1