0

While writing the program, I encountered the need to handle multiple errors in one block. The client can return errors that are inherited from more than one class. It is necessary to separately handle errors with status code 4xx and code 5xx. Each error inherits strictly from two known classes and differ only in the class name. I decided that one of the ways to handle this case is to catch one base class and somehow get the second one. What is the safest way to get the second ancestor class from the first?

// begin of external library
class ExceptionWithStatusCode : public std::exception {
    int status_code;
};

struct Details {};
class ErrorResponseModel {
    Details details;
};

class Response400 : public ExceptionWithStatusCode, ErrorResponseModel {};
class Response401 : public ExceptionWithStatusCode, ErrorResponseModel {};
class Response500 : public ExceptionWithStatusCode, ErrorResponseModel {};
class Response501 : public ExceptionWithStatusCode, ErrorResponseModel {};
// end of external library

int main()
{
    try {
        do_request();
    } catch (const ExceptionWithStatusCode& ex) {
        if (ex.status_code < 500) {
            // handle 4xx using ErrorResponseModel::details
        } else {
            // handle 5xx using ErrorResponseModel::details
        }
    }
    
    return 0;
}
  • it is recommended to inherit from `std::runtime_error` then catch `std::exception&` – 463035818_is_not_an_ai May 11 '23 at 08:27
  • First of all, catch references. Secondly, what is the original problem? Why can't you catch `B&`? Why do your exception classes need to inherit from both `A` and `B`? Please [edit] your question to tell us about the original and actual problem you're trying to solve. – Some programmer dude May 11 '23 at 08:28
  • if you catch by value there is object slicing https://stackoverflow.com/questions/274626/what-is-object-slicing – 463035818_is_not_an_ai May 11 '23 at 08:28
  • There's no way to do this because you have a case of [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing). There is no `B` object to get. Maybe if you caught a reference `const A& ex` you might be able to do something. – john May 11 '23 at 08:28
  • The original classes were `Response400,401,402,...`. Each `Response4xx` inherit from two classes: `ExceptionWithStatusCode` and `ErrorResponseModel`. `ExceptionWithStatusCode` inherits from `std::exception`. `ExceptionWithStatusCode` contains status code only and `ErrorResponseModel` contains some details – Trifochkin Semyon May 11 '23 at 08:37
  • @john, yes, i forgot. Of course i use `const A&`. Thought it could be removed for simplicity – Trifochkin Semyon May 11 '23 at 08:39
  • Is there any reason why you don't have a `virtual` member function in your exception classes that provides the message (similarly to `std::exception::what()`)? – UnholySheep May 11 '23 at 08:46
  • @UnholySheep, I use a library that I cannot change. Details are structured and there is not one string at all – Trifochkin Semyon May 11 '23 at 08:55
  • 1
    Can you change the `Response400` etc. classes? To have a common `Response4xx` base class (which have the double inheritance), and then make e.g. `Response400` inherit from the new `Response4xx` class? – Some programmer dude May 11 '23 at 08:56
  • @Someprogrammerdude, i thought about that too. But no, i can't – Trifochkin Semyon May 11 '23 at 08:58
  • Relevant question: [Multiple inheritance casting from base class to different derived class](https://stackoverflow.com/q/7426422/5481471) – G. Sliepen May 11 '23 at 13:33

0 Answers0