• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Wyjątki try i dwa bloki catch

Object Storage Arubacloud
+1 głos
188 wizyt
pytanie zadane 7 grudnia 2016 w C i C++ przez Kasztan Dyskutant (8,080 p.)
zamknięte 8 grudnia 2016 przez Kasztan
#ifndef HEADER_H_
#define HEADER_H_

#include "stdafx.h"
#include <iostream>
#include <stdexcept>
#include <string>

using namespace std;

class Sales
{
public:
	enum { MONTHS = 12 };     // could be a static const
	class bad_index : public logic_error
	{
	private:
		int bi; // bad index value
	public:
		explicit bad_index(int ix, const string & s = "Index error in Sales object\n");
		int bi_val() const { return bi; }
		virtual ~bad_index() throw() {}
	};

	explicit Sales(int yy = 0);
	Sales(int yy, const double * gr, int n);
	virtual ~Sales() {}
	int Year() const { return year; }
	virtual double operator[](int i) const;
	virtual double & operator[](int i);

private:
	double gross[MONTHS];
	int year;
};

class LabeledSales : public Sales
{
public:
	class nbad_index : public Sales::bad_index
	{
	private:
		string lbl;
	public:
		nbad_index(const string & lb, int ix, const string & s = "Index error in LabeledSales object\n");
		const string & label_val() const { return lbl; }
		virtual ~nbad_index() throw() {}
	};

	explicit LabeledSales(const string & lb = "none", int yy = 0);
	LabeledSales(const string & lb, int yy, const double * gr, int n);
	virtual ~LabeledSales() {}
	const string & Label() const { return label; }
	virtual double operator[](int i) const;
	virtual double & operator[](int i);

private:
	string label;
};

#endif // !HEADER_H_




#include "stdafx.h"
#include <iostream>
#include <string>
#include "Header.h"

using namespace std;



Sales::bad_index::bad_index(int ix, const string & s)
	: std::logic_error(s), bi(ix)
{
}

Sales::Sales(int yy)
{
	year = yy;
	for (int i = 0; i < MONTHS; i++)
		gross[i] = 0;
}

Sales::Sales(int yy, const double * gr, int n)
{
	year = yy;
	int lim = (n < MONTHS) ? n : MONTHS;
	int i;

	for (i = 0; i < lim; i++)
		gross[i] = gr[i];

	for (; i < MONTHS; i++)
		gross[i] = 0;
}

double Sales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

double & Sales::operator[](int i)
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

LabeledSales::nbad_index::nbad_index(const string & lb, int ix,
	const string & s) : Sales::bad_index(ix, s)
{
	lbl = lb;
}

LabeledSales::LabeledSales(const string & lb, int yy)
	: Sales(yy)
{
	label = lb;
}

LabeledSales::LabeledSales(const string & lb, int yy,
	const double * gr, int n)
	: Sales(yy, gr, n)
{
	label = lb;
}

double LabeledSales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator[](i);
}

double & LabeledSales::operator[](int i)
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator[](i);
}
#include "stdafx.h"
#include <iostream>
#include "Header.h"

using namespace std;

int main()
{
	
	double vals1[12] =
	{
		1220, 1100, 1122, 2212, 1232, 2334,
		2884, 2393, 3302, 2922, 3002, 3544
	};

	double vals2[12] =
	{
		12, 11, 22, 21, 32, 34,
		28, 29, 33, 29, 32, 35
	};

	Sales sales1(2011, vals1, 12);
	LabeledSales sales2("Blogstar", 2012, vals2, 12);

	cout << "First try block:\n";
	try
	{
		int i;
		cout << "Year = " << sales1.Year() << endl;
		for (i = 0; i < 12; ++i)
		{

			cout << sales1[i] << ' ';
			if (i % 6 == 5)
				cout << endl;
		}
		cout << "Year = " << sales2.Year() << endl;
		cout << "Label = " << sales2.Label() << endl;
		for (i = 0; i <= 12; ++i) // to powoduje wywolanie bloku try and catch
		{

			cout << sales2[i] << ' ';
			if (i % 6 == 5)
				cout << endl;
		}
		cout << "End of try block 1.\n";
	}
	catch (LabeledSales::nbad_index & bad)
	{
		cout << bad.what();
		cout << "Company: " << bad.label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}
	catch (Sales::bad_index & bad)
	{
		cout << bad.what();
		cout << "bad index: " << bad.bi_val() << endl;
	}



	cout << "\nNext try block:\n";
	try
	{
		sales2[2] = 37.5;
		sales1[20] = 23345;
		cout << "End of try block 2.\n";
	}
	catch (LabeledSales::nbad_index & bad)
	{
		cout << bad.what();
		cout << "Company: " << bad.label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}
	catch (Sales::bad_index & bad)
	{
		cout << bad.what();
		cout << "bad index: " << bad.bi_val() << endl;
	}
	cout << "done\n";

	return 0;
}

Po każdym bloku try znajdują się dwa bloki catch dzięki czemu zgłoszenie wyjątku nbad_index prowadzi do wywołania metody label_val(). Zmodyfikuj ten program tak, aby po każdym bloku try był jeden blok catch. Do sprawdzenia czy należy użyć metody label_val(), użyj mechanizmu RTTI.

Jakie macie pomysły na to zadanie czy zrobić trzecią klasę która dziedziczy po klasie LabeledSales ? Czy jak mam to zrobić ?

komentarz zamknięcia: Uzyskałem odpowiedź

1 odpowiedź

0 głosów
odpowiedź 8 grudnia 2016 przez criss Mędrzec (172,590 p.)
wybrane 8 grudnia 2016 przez Kasztan
 
Najlepsza

Z tym RTTI prawdopodobnie chodzi o dynamic_cast.

Napisz block catch który złapie referencje do obiektu Sales::bad_index. Jako że LabeledSales::nbad_index z niego dziedziczy, to też zostanie złapany (polimorfizm). I następnie dynamic_cast-em upewnij czy być może jest to obiekt LabeledSales::nbad_cast.

Przykład:

struct ExcBase : public std::logic_error
{
   ExcBase(std::string s) : std::logic_error(s) { }
   void m1() { std::cout << "base's method\n"; }
   virtual ~ExcBase() { }
};

struct Exc : public ExcBase
{
   Exc(std::string s) : ExcBase(s) { }
   void m2() { std::cout << "derived's method\n"; }
};

void f() { throw Exc("error"); }

int main()
{
   try
   {
      f();
   }
   catch(ExcBase & e)
   {
      std::cout << e.what() << '\n';
      e.m1();
      if(Exc * ptr = dynamic_cast<Exc *>(&e))
         ptr->m2();
   }
}

Jeśli w f() podmienisz żeby rzucało obiekt ExcBase, to m2() się nie wykona (bo cast się nie powiedzie).

Btw, lepiej żebyś nie używał using namespace w headerach, bo taki using staje się "aktywny" we wszystkich plikach gdzie zostanie taki header zaincludowany. Może ci przysporzyć kłopotów kiedyś. Oczywiście możesz zamknąć ten using w klamrach klasy i będzie w porządku.

komentarz 8 grudnia 2016 przez Kasztan Dyskutant (8,080 p.)
Dzięki jak zawsze za pomoc :)
komentarz 8 grudnia 2016 przez criss Mędrzec (172,590 p.)
Prosze :)

Podobne pytania

0 głosów
2 odpowiedzi 683 wizyt
pytanie zadane 3 lipca 2018 w Java przez periedynek Obywatel (1,320 p.)
+1 głos
1 odpowiedź 314 wizyt
pytanie zadane 5 maja 2021 w C i C++ przez Mavimix Dyskutant (8,390 p.)
0 głosów
2 odpowiedzi 146 wizyt
pytanie zadane 28 marca 2021 w C i C++ przez Mavimix Dyskutant (8,390 p.)

92,580 zapytań

141,433 odpowiedzi

319,665 komentarzy

61,966 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...