Exception member class OOP
Exception member class OOP
I have met the following concept in the production code:
class A
{
public:
class Exception : public std::exception
{/* ... */};
//...
};
Nobody can give me a clear answer why it is like this. My question is whether this approach is in line with SOLID rules? I think that would be better if this exception class is located outside the class A and is injected while creating the instance of A.
You are right. Injecting is not necessary, because the independent exception class will be available to class A "in normal way". However, I still cannot explain why the exception class should be a member of class A.
– artona
Jul 2 at 6:54
I think that you would find an answer if you went ahead and implemented your suggestion.
– molbdnilo
Jul 2 at 6:56
If it's an error specific to
A
it feels kind of "clean" to write catch(A::Exception const& e) {..}
. Depends on how much the error can be re-used or is specific to A
. I don't think there's an all encompassing answer. It depends on the types in question, and is very much a judgement call. But it personally makes sense to me that an error is part of a classes interface.– StoryTeller
Jul 2 at 6:58
A
catch(A::Exception const& e) {..}
A
3 Answers
3
You may want to read : https://en.cppreference.com/w/cpp/language/nested_types
Because you say "is injected while creating the instance A", I think I need to clarify that Exception
being defined as an inner-class doesn't make it a member of instances of A
. If you want to make it a member of the instances of A
you'd have to explicitely declare the member in A
: Exception m_expections;
Exception
A
A
A
Exception m_expections;
When you say "injected while creating the instance of A", note that Exception
is a type, not an object. You can't have different type members in instances of the same class.
Exception
You can use different types in different instantiations of a class template (i.e. different classes), but for this example, you don't need a template.
It's perfectly normal for classes to have inner types. You collect all the ancillary definitions into one container. std::map
has 18 member types. Class name scope is almost identical to namespace scope in that regard.
std::map
My question is whether this approach is in line with SOLID rules?
I don't think there is anything is SOLID that would sustain or prohibit this.
I would still have a problem with this, because of naming and semantics: When you declare an exception like this, the only thing it can mean is "the type of exception generated by class A". This does not accurately represent any type of error condition (though I doubt that you have a class really named A
, so maybe the meaning is lost due to the name chosen in your example).
A
If the class name is really "Exception" you should probably rename it. It also doesn't make sense to me to define it in the class (I can see no reason for it).
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Design principles are important, but they aren't followed "because they are design principles". They are followed because they accomplish something. What would injecting the exception object upon construction accomplish? Now the class should manage this objects lifetime. What if an error state is never encountered, and it's never thrown?
– StoryTeller
Jul 2 at 6:16