Try catch, throw w konstruktorze

0

W jaki sposób mógłbym użyć try catch jeżeli chcę aby w klasie Triangle sprawdzane były odległości między punktami i ew. został zwrócony wyjątek.

Jak na razie zrobiłem coś takiego:
main:

try
	{
		Triangle t1(A, B, C);
	}
	catch (string w)
	{
		cout << "Wyjatek: " << w;
	}

konstruktor Triangle:

Triangle::Triangle(Point p1, Point p2, Point p3) : a(p1), b(p2), c(p3)
{
	string wyjatek = "jakis blad";
	if (a.x = 2)
	{
		throw wyjatek;
	}
}

W mainie wywołuję również kilka metod klasy Triangle i z powodu, że sprawdzanie jest zamknięte w bloku nie znajduje mi tego obiektu. Jest jakiś sposób żeby sprawdzać ten wyjątek a jednocześnie móc używać tych metod w mainie? Dodam, że pierwszy raz używam obsługi wyjątków try ,catch.

0

Jest jakiś sposób żeby sprawdzać ten wyjątek a jednocześnie móc używać tych metod w mainie? Dodam, że pierwszy raz używam obsługi wyjątków try ,catch.
To nie brzmi jak dobry design. Jeśli obiekt Triangle nie został utworzony, to czemu chciałbyś móc na nim wywoływać metody?

0

Ostatecznie chce to wszystko zamknąć w jakiejś pętli tak żeby punkty wpisywać seterami, do czasu aż nie będą dobre.

0

ale co i po co chcesz rzucać w trójkącie przyjmującym 3 punkty? Przecież nie będzie tu żadnych dziwnych stanów, a jeśli coś w obliczeniach nie będzie pasować to w metodzie to liczącej możesz rzucać.

Ps. settery są złe, zniszczą Cie.

3
  1. struktury typu trójkąt powinny mieć jak najmniej logiki w konstruktorach
  2. w konstruktorze wyjątek będzie upierdliwy, w strukturze podwójnie
  3. do rzucania używaj klasy pochodne od std::exception dzięki czemu nie będziesz musiał mieć w main catch dla każdego typu a jedynie dla właśnie tej klasy
    http://www.cplusplus.com/doc/tutorial/exceptions/
  4. jak chcesz mieć rozbudowany konstruktor to pomyśl lepiej o builderze:
    https://pl.wikipedia.org/wiki/Budowniczy_(wzorzec_projektowy)
2

Jak widzę jawne throw w konstruktorze to od razu zakładam, że z kodem jest coś nie tak. W tym przypadku lepiej byłoby użyć jakiegoś budowniczego i idealnie Boost.Optional albo std::optional bo wyjścia masz dwa, albo możesz stworzyć trójkąt z punktów albo nie, więc wyjątków tak na dobrą sprawę nie potrzebujesz. Ale jak pozostaniemy przy wyjątkach to wtedy tak (pseudokod):

class Triangle
{
public:
     // jak mamy optionale to create powinien go zwrocic
     static Triange crete(arguments){
          if(canCreateTriangleFromPoints(arguments)){
              return Triangle(arguments);
          }
          throw exception;
      }
     
private:
     Triangle(arguments);
     static bool canCreateTriangleFromPoints(arguments);
};


main(){
      try{
         auto tr = Triangle::create(arguments);
      }
      catch(exception)
      { // handle error}
      
}

EDIT
A jak potrzebujesz jakiś szczegółów co w obliczeniach poszło nie tak, to powinieneś mieć osobną klasę pod tytułem TrianglePointsInspector czy jakoś tak, która zwróci Ci szczegóły, a konstrukcja Triangle powinna pozostać binarna i idealnie z optionalami.

4

Przesadzacie. Ideą konstruktora jest stworzenie POPRAWNEGO obiektu. Kluczowym jest tu słowo "poprawnego". Jeśli z jakiegoś powodu konstruktor nie może utworzyć poprawnego obiektu, to jak najbardziej może rzucać wyjątek. A nawet powinien. Tutaj wyjątek powinien być rzucony, jeśli warunek istnienia trójkąta nie zostanie spełniony.

0

Jeśli weźmiemy pod uwagę co ten konstruktor musi sprawdzać:
https://stackoverflow.com/a/2049593

i założymy na chwilę że w C++ obecnie ogólnie projektuje i programuje się głównie dla wydajności, to nagle staje się oczywiste że konstruktor takiego rodzaju jest co najmniej wątpliwy.

Nie wyobrażam sobie przetwarznia miliona trójkątów z takimi konstruktorami.
Chyba że mówimy o programie edukacyjnym dla dzieci - wtedy OK.

Można oczywiście sobie zrobić otagowany konstruktor jeśli wzorzec budowniczego to za duży kłopot.
http://www.cplusplus.com/forum/general/151801/

Teoretycznie narzut takiego tagowania jest zerowy - ale nie sprawdzałem.

0

Dziwne pytanie. Przecież skoro tworzysz obiekt w try to wszystkie działania na nim też muszą się w nim zawrzeć. No bo jak? Będziesz pracować na niezainicjowanym obiekcie? Zupełnie abstrachując od tego, że w kodzie jest bład i raczej miało być a.x == 2 (bo a.x = 2 jest zawsze 2 czyli prawda) i od tego, że trudno mi sobie wyobrazić, żeby taki konstruktor miał rzucić wyjątek, może w skrajnym przypadku, jeśli wszystkie punkty leżą na jednej prostej, bo wtedy ciężko mówić o trójkącie.
Generalnie odradzam wpychanie rozwiązań na siłę, żeby poćwiczyć. A nuż nauczyłbyś się pisać bez wyjątków. Obsypali by cię złotem. xD A tak na serio, to skup się na tym, żeby zrobić coś użytecznego, bo to jest istotne w programowaniu. A wyjątki to raczej zło konieczne. :P

0
vpiotr napisał(a):

Nie wyobrażam sobie przetwarznia miliona trójkątów z takimi konstruktorami.
Chyba że mówimy o programie edukacyjnym dla dzieci - wtedy OK.

Jeśli robisz aplikację graficzną, to jasne że tego nie będziesz sprawdzał, bo tu wydajność jest na pierwszym miejscu. Ale raczej sam nie podajesz punktów, żeby stworzyć trójkąt, tylko modele przychodzą z zewnątrz. Więc to by było raczej bez sensu. Bo model z zewnątrz zawsze będzie się składał z poprawnych trójkątów. W innym przypadku (aplikacja niegraficzna, gdzie sam podajesz punkty) można coś takiego zrobić. Jeśli sprawdzanie faktycznie za długo trwa (nie optymalizuj przedwcześnie), to zawsze można je włączyć tylko w wersji debugowej.

W builder też nie po to powstał. To byłoby zbytnie komplikowanie banalnego problemu (łamanie zasady KISS).

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