Projekt klasy wyjątków C ++ [zamknięty]

Jaki jest dobry projekt dla zestawu klas wyjątków?

Widzę wiele różnych rzeczy na temat tego, jakie klasy wyjątków powinny i nie powinny robić, ale nie prostego projektu, który jest łatwy w użyciu i rozszerzeniu, który wykonuje te rzeczy.

Klasy wyjątków nie powinny rzucać wyjątków, ponieważ może to prowadzić bezpośrednio do zakończenia procesu bez możliwości zarejestrowania błędu itp.Musi być możliwe uzyskanie przyjaznego dla użytkownika ciągu, najlepiej zlokalizowanego w ich języku, tak aby było coś do powiedzenia, zanim aplikacja zakończy się, jeśli nie może odzyskać po błędzie.Musi istnieć możliwość dodawania informacji w miarę rozwijania stosu, na przykład, jeśli analizator składni XML nie może przeanalizować strumienia wejściowego, aby móc dodać, że źródło pochodzi z pliku lub przez sieć itp.Procedury obsługi wyjątków wymagają łatwego dostępu do informacji potrzebnych do obsługi wyjątku.Napisz sformatowane informacje o wyjątku do pliku dziennika (w języku angielskim, więc nie ma tu tłumaczeń).

Pierwsze 1 i 4 do współpracy to największy problem, jaki mam, ponieważ wszelkie metody formatowania i wyjścia plików mogą potencjalnie zawieść.

EDIT: Tak więc po przejrzeniu klas wyjątków w kilku klasach, a także w pytaniu Neila, z którym się łączy, wydaje się, że powszechną praktyką jest po prostu całkowite zignorowanie punktu 1 (a tym samym zaleceń dotyczących zwiększenia), co wydaje się raczej złym pomysłem mnie.

W każdym razie pomyślałem, że opublikuję także klasę wyjątków, o której myślę.

class Exception : public std::exception
{
    public:
        // Enum for each exception type, which can also be used
        // to determine the exception class, useful for logging
        // or other localisation methods for generating a
        // message of some sort.
        enum ExceptionType
        {
            // Shouldn't ever be thrown
            UNKNOWN_EXCEPTION = 0,

            // The same as above, but it has a string that
            // may provide some information
            UNKNOWN_EXCEPTION_STR,

            // For example, file not found
            FILE_OPEN_ERROR,

            // Lexical cast type error
            TYPE_PARSE_ERROR,

            // NOTE: in many cases functions only check and
            //       throw this in debug
            INVALID_ARG,

            // An error occured while trying to parse
            // data from a file
            FILE_PARSE_ERROR,
        }

        virtual ExceptionType getExceptionType()const throw()
        {
            return UNKNOWN_EXCEPTION;
        }

        virtual const char* what()throw(){return "UNKNOWN_EXCEPTION";}
};


class FileOpenError : public Exception
{
    public:
        enum Reason
        {
            FILE_NOT_FOUND,
            LOCKED,
            DOES_NOT_EXIST,
            ACCESS_DENIED
        };
        FileOpenError(Reason reason, const char *file, const char *dir)throw();
        Reason getReason()const throw();
        const char* getFile()const throw();
        const char* getDir ()const throw();

    private:
        Reason reason;
        static const unsigned FILE_LEN = 256;
        static const unsigned DIR_LEN  = 256;
        char file[FILE_LEN], dir[DIR_LEN];
};

Punkt 1 jest adresowany, ponieważ wszystkie łańcuchy są obsługiwane przez kopiowanie do wewnętrznego, stałego bufora rozmiaru (w razie potrzeby obcinanie, ale zawsze kończy się wartością zerową).

Chociaż to nie odnosi się do punktu 3, jednak myślę, że punkt ten i tak najprawdopodobniej ma ograniczone zastosowanie w realnym świecie, i najprawdopodobniej można go rozwiązać, rzucając nowy wyjątek, jeśli zajdzie taka potrzeba.

questionAnswers(6)

yourAnswerToTheQuestion