Oto przykład tego, co często robię, gdy chcę dodać informacje do wyjątku:
std::stringstream errMsg;
errMsg << "Could not load config file '" << configfile << "'";
throw std::exception(errMsg.str().c_str());
Czy jest na to lepszy sposób?
Oto przykład tego, co często robię, gdy chcę dodać informacje do wyjątku:
std::stringstream errMsg;
errMsg << "Could not load config file '" << configfile << "'";
throw std::exception(errMsg.str().c_str());
Czy jest na to lepszy sposób?
std∷exception
nie masz konstruktora zchar*
arg.std::string
ma domyślnego konstruktora, który pobieraconst char*
...std::exception
klas podrzędnych firmy MS i jest używany przez ich wersjestd::runtime_error
istd::logic_error
. Oprócz tych zdefiniowanych przez standard, wersja MSVS<exception>
zawiera jeszcze dwa konstruktory, jeden bierze,(const char * const &)
a drugi bierze(const char * const &, int)
. Są używane do ustawiania zmiennej prywatnejconst char * _Mywhat
,; jeśli_Mywhat != nullptr
, towhat()
domyślnie zwraca go. Kod, który się na nim opiera, prawdopodobnie nie jest przenośny.Odpowiedzi:
Oto moje rozwiązanie:
Przykład:
źródło
Standardowe wyjątki można zbudować z
std::string
:Zauważ, że klasa bazowa nie
std::exception
może zostać w ten sposób skonstruowana; musisz użyć jednej z konkretnych, pochodnych klas.źródło
Istnieją różne wyjątki, takie jak
runtime_error
,range_error
,overflow_error
,logic_error
, etc .. Trzeba przekazać ciąg do jego konstruktora, a można łączyć, co chcesz do wiadomości. To tylko operacja na łańcuchu.Możesz także użyć w
boost::format
ten sposób:źródło
Następująca klasa może się bardzo przydać:
Przykład użycia:
źródło
throw std::runtime_error(sprintf("Could not load config file '%s'", configfile.c_str()))
throw std::runtime_error("Could not load config file " + configfile);
(wstd::string
razie potrzeby konwertowanie jednego lub innego argumentu na ).printf
i przyjaciele są nieuchronni w C ++ 11. Bufor o stałym rozmiarze jest zarówno błogosławieństwem, jak i przekleństwem: nie zawodzi w sytuacjach niskiego poziomu zasobów, ale może obciąć wiadomość. Uważam, że skrócenie komunikatu o błędzie jest lepszą opcją niż niepowodzenie. Również wygoda ciągów formatujących została udowodniona w wielu różnych językach. Ale masz rację, to w dużej mierze kwestia gustu.Użyj operatora literału ciągu, jeśli C ++ 14 (
operator ""s
)lub zdefiniuj własne, jeśli w C ++ 11. Na przykład
Twoje oświadczenie o rzucie będzie wtedy wyglądać tak
który wygląda ładnie i czysto.
źródło
Naprawdę przyjemniejszym sposobem byłoby utworzenie klasy (lub klas) dla wyjątków.
Coś jak:
Powodem jest to, że wyjątki są znacznie lepsze niż zwykłe przesyłanie łańcucha. Zapewniając różne klasy dla błędów, dajesz programistom szansę na obsłużenie określonego błędu w odpowiedni sposób (a nie tylko wyświetlenie komunikatu o błędzie). Jeśli korzystasz z hierarchii, osoby wychwytujące Twój wyjątek mogą być tak szczegółowe, jak potrzebują.
a) Być może trzeba będzie znać konkretny powód
a) inny nie chce znać szczegółów
Inspirację na ten temat można znaleźć w https://books.google.ru/books?id=6tjfmnKhT24C Rozdział 9
Ponadto, można dostarczyć niestandardowy komunikat zbyt, ale należy zachować ostrożność - nie jest to bezpieczne, aby utworzyć wiadomość z albo
std::string
albostd::stringstream
albo jakikolwiek inny sposób, który może spowodować wyjątek .Generalnie nie ma różnicy, czy alokujesz pamięć (pracujesz z napisami w sposób C ++) w konstruktorze wyjątku, czy tuż przed wyrzuceniem -
std::bad_alloc
wyjątek można wyrzucić przed tym, który naprawdę chcesz.Tak więc bufor przydzielony na stosie (jak w odpowiedzi Maxima) jest bezpieczniejszym sposobem.
Jest to bardzo dobrze wyjaśnione na http://www.boost.org/community/error_handling.html
Więc lepszym sposobem byłby określony typ wyjątku i unikanie tworzenia sformatowanego ciągu (przynajmniej podczas rzucania).
źródło
Napotkałem podobny problem, ponieważ tworzenie niestandardowych komunikatów o błędach dla moich niestandardowych wyjątków powoduje brzydki kod. To było moje rozwiązanie:
To oddziela logikę tworzenia wiadomości. Początkowo myślałem o nadpisaniu what (), ale potem musisz gdzieś przechwycić swoją wiadomość. std :: runtime_error ma już wewnętrzny bufor.
źródło
Może to?
Tworzy tymczasowy strumień ostringstream, w razie potrzeby wywołuje operatory <<, a następnie zawijasz go w nawiasy okrągłe i wywołujesz funkcję .str () na ocenianym wyniku (którym jest strumień ostringstream), aby przekazać tymczasowy std :: string do konstruktora błędu runtime_error.
Uwaga: strumień ostringstream i string są tymczasowymi wartościami r, więc po zakończeniu tej linii wychodzą poza zakres. Konstruktor obiektu wyjątku MUSI pobrać ciąg wejściowy przy użyciu semantyki kopiowania lub (lepiej) przenoszenia.
Dodatkowe: niekoniecznie uważam to podejście za „najlepszą praktykę”, ale działa i można je stosować w mgnieniu oka. Jednym z największych problemów jest to, że ta metoda wymaga alokacji sterty, więc operator << może rzucać. Prawdopodobnie nie chcesz, aby tak się stało; Jednak jeśli dojdziesz do tego stanu, prawdopodobnie będziesz miał więcej problemów do zmartwienia!
źródło