Przechwytywanie wyjątków

0

Witam. Czytałem w jaki sposób w c++ przechwycić wyjątek i stosownie się zachować. Postanowiłem przejść od słów do czynów, ale coś nie wyszło. Po wykryciu wyjątku program miał wyświetlić w konsoli kreślony tekst. Jednak zamiast tekstu program przerywa swoje działanie z takim komunikatem:

 
int main()
{
	class p1won{};
	class p2won{};
	
	srand(time(NULL));
	int round = 13;
	Dice d1;
	Dice d2;
	game_info();
	while (round <= 13)
	{
		srand(time(NULL));
		
		d1.random_numbers(0);
		d1.random_again(0,0);
		system("cls");
		cout << players_tab[0].name << endl;
		system("cls");

		d2.random_numbers(1);
		d2.random_again(1,1);
		system("cls");
		cout << players_tab[1].name << endl;
		system("cls");
	
		if (round == 13)
		{
			cout << "Player: " << players_tab[0].name << ", " << "Points: " << players_tab[0].points << endl;
			cout << "Player: " << players_tab[1].name << ", " << "Points: " << players_tab[1].points << endl;
			
			try
			{
				if (players_tab[0].points > players_tab[1].points)
				{
					//cout << "Player: " << players_tab[0].name << "Won !" << endl;
					throw p1won();

				}
				else
				{
					throw p2won();
					//cout << "Player: " << players_tab[1].name << "Won !" << endl;
				}

			}//try
			catch (p1won())
			{
				cout << "Player: " << players_tab[0].name << "Won !" << endl;
			}
			catch (p2won())
			{
				cout << "Player: " << players_tab[1].name << "Won !" << endl;
			}


		}//if
		
		round++;
	
	}

	system("pause");
	return 0;
}
0

Tak trochę to dziwnie wygląda. Po co rzucasz pustą klasę wyjątku i w dodatku wtedy kiedy ktoś wygra?

  • Rzucaj obiektem klasy, która ma w sobie jakieś informacje. Pusta klasa wyjątku niczego nie wnosi;
  • Jeżeli gracz wygrywa to to chyba nie jest sytuacja wyjątkowa..?;
#include<iostream>
#include<string>
using namespace std;

class generic_exception
{
protected:
    int code;
    string message;

public:
    generic_exception(int code, const string& message) : code(code), message(message){}
};

class dice_exception : public generic_exception
{
public:
    dice_exception() : generic_exception(255, "For example: Some example exception ;)"){}
    string to_string() const { return "Code: " + std::to_string(this->code) + " Message: " + this->message; }
};

void foo()
{
    throw dice_exception();
}

int main()
{
    try
    {
        foo();
    }
    catch(const dice_exception& de)
    {
        cout << de.to_string() << endl;
    }

    return 0;
}
5

Nie do końca się zgadzam. Sam typ wyjątku jest unikalną i często wystarczającą informacją (czy potrzebujesz wołać what() na std::bad_alloc?).

Jednak używanie wyjątków do informowania o normalnym (niewyjątkowym!) wykonaniu programu to błąd, nie do tego są one przeznaczone.

Tak czy inaczej, klauzyle catch są u Ciebie źle zdefiniowane, ale się kompilują "dzięki" zawiłości definicji w C, a zatem i w C++. Dałeś się złapać w tzw. "Most Vexing Parse":

catch (p1won())

Złapie wyjątek będący funkcją przyjmującą 0 argumentów i zwracającą obiekt klasy p1won :D

Powinieneś napisać:

catch(p1won const&)
0

@kq dzięki, Twój sposób zadziałał, ale chcialem to zrobić bardziej "elegancko" tak jak w przykladzie podal @grzesiek51114. Jednak coś jest nie tak. Nie kompiluje się mój kod już po przerobieniu jak i oryginalny kod jaki podał @grzesiek51114.

plik Dicee.cpp

try
		{
				if (tmp_dice < 1 || tmp_dice > 6)
				{
					throw  dice_exception();
				}
				dices_tab.push_back(tmp_dice);

	
		}//try
		catch (const dice_exception& de)
		{
			cout << de.err_dice_number() << endl;
		}
 

Plik exceptions.h

 

#ifndef exceptions
#define exceptions
#include<string>


using namespace std;
class exception_generator
{
public:
	int error_code;
	string message;
	exception_generator(int error_code, const string& message)
	
		:error_code(error_code),
		message(message)
	{}
};


	class dice_exception : public exception_generator
	{
	public:
		dice_exception() : exception_generator(1, "Error.Bad random number of dice") {};
		string err_dice_number()
	const {
			return "Code: " + err_dice_number(this->error_code) + " Message: " + this->message;
		  }

	};

#endif

Kompilator krzyczy tutaj

		return "Code: " + err_dice_number(this->error_code) + " Message: " + this->message; 

Ja rozumiem to tak: err_dice_number jest wywoływane z parametrem czyli err_code. Problem w tym, że err_code jest nie przyjmuje parametrów w swojej deklaracji, więc logiczne, żę nie można wywołać czegoś z parametrem, który nie został zadeklarowany na wejściu. Nie mam pojęcia jednak jak to zmienić, żeby działało.
Gdy zrobię tak:

return  " Message: " + this->message; 

elegancko jest zwracany komunikat, ale ja jeszcze chce, żeby podany był kod błędu ( w tym przypadku kod 1)

0
  1. Formatuj kod jakoś porządnie bo ciężko się to czyta.
  2. za niedziedziczenie wyjątków po std::exception powinni wieszać za jaja (lub jajniki).
  3. próbujesz wywołać rekursywnie err_dice_number. Nie do końca rozumiem co tam chcesz zrobić. Jeśli chcesz przekazać parametr do konstruktora dice_exception, aby móc potem o nim informować to zrób to. To jest normalna klasa.

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