2

Whenever I want to share an enum among many files I will :-

  • create a class e.g. B dedicated to the enum
  • a class, which want to access to the enum easily, will derived from B

Mostly, there will be one class for one enum. (1:1)

class B{
    public: enum EnumB{ E1,E2 };  
};
class C : public B{ /* .... access EnumB */}; //a kind of struct
class D : public B{ /* .... access EnumB */}; //a kind of widget/manager

This approach enables C and D to access EnumB without any prefix B.

I think it is OK, because I use those enum in a very-narrow scope. (2-4 classes)
A SO post also states it is OK to use inheritance for utility.

However, I don't find that it is a popular approach :-

Question

  • How my approach is dangerous? What is its disadvantages?

    In real case, I tend to multi-inherit many classes just for that.

    class ShadowEnum{ public: enum ShadowE{ SHADOW,NO_SHADOW};   };
    class ColorEnum{  public: enum ColorE{ RED,BLUE,GREEN,PURPLE } };  
    class LightType{  public: enum LightE{ L_SPHERE, L_CONE, L_SPOT};   };   
    class LightManager : public ShadowEnum, public ColorEnum,public LightType{
         /* some code */
    };
    
  • Can it be a cause of a dread-diamond issue in future?

By the way, I think enum-class is not in the scope of this question.

Community
  • 1
  • 1
javaLover
  • 6,347
  • 2
  • 22
  • 67
  • Whilst personally I wouldn't be inheriting from the enum specific class (I'd just accept the use of the prefix), but if you want to use inheritance it seems to me that private inheritance would meet your needs whilst also addressing some of concerns. Private inheritance doesn't imply the is-a relationship. – ROX Mar 13 '17 at 14:32

1 Answers1

3

It's not "dangerous" per-se. It's just bad design.
Class inheritance is supposed to define an IS-A relationship.

When inheriting from something that isn't "natural", you tend to get problems later along the development road.

Some of this design implications that could affect you are:
1. Multiple inheritance of the same class in a deeper inheritance graph.
2. Pointer casts may be affected if you change the inheritance structure in the future (Which is something you don't want to happen just for a convenience inheritance)

A couple of better solutions:
1. Contain the enums in a namespace - use #using namespace. Adding that in the header will propagate to any compilation unit that includes that header.
2. In C++11 you can just use enum classes - Not in inheritance, but it gives you stronger type safety.

Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • Thank..... In both solutions, I have to call `SomePrefix::` right? .... `#using namespace` is not so cute - [I can't use it at class-level](http://stackoverflow.com/q/6326805/3577745). .... "Pointer casts may be affected" possible? It is just an enum (size~0), no address shift... please elaborate – javaLover Mar 12 '17 at 07:35
  • 1
    @javaLover I agree with your considering "cannot limit `using` to class scope" impure. But pragmatically it is probably not a big issue: Often a file will only contain definitions for only one class anyway. In any case the code should be related, and it's not unlikely that much of it will need the enums. That need could even serve as a criteria for arranging code in files. – Peter - Reinstate Monica Mar 12 '17 at 07:42
  • 1
    @javaLover I didn't get why you are putting enum in a `Some` class if you don't want to call as `Some::` ? – JustRufus Mar 12 '17 at 07:43
  • If it's only these classes than it may not be a problem. But if you have multiple such classes, and a deeper inheritance tree, it can lead to human mistakes in code maintenance. Having all these classes in an inheritance tree would imply that you need to document the intention and the rules, for the next programmer. If you don't very quickly some other programmer will add a convenient member to one of those classes (because he can). Then everything will get messed up. – Yochai Timmer Mar 12 '17 at 07:45
  • @JustRufus because I can't find a true better way. The alternative are **1.** put it in namespace -> I still have to `Some::` **2.** put it in a global scope -> too dangerous **3.** put it in a class --> I have to call `Some::`, but I can also cheat by inheritance! – javaLover Mar 12 '17 at 07:46
  • @javaLover and for the using namespace issue - It's not per class, but per compilation unit. So technically adding that "#using namespace" in the same header where you had the LightManager class declaration will indeed include that namespace into whatever classes that include that header. – Yochai Timmer Mar 12 '17 at 07:47
  • Now that you say that: That there is an implicit conversion to the base classes containing enums may be a desired effect; i.e. one can pass a `LightManager` to a function expecting a Color, which doesn't seem unreasonable. This assumes that colors in the OP's code are generally communicated by the class `ColorEnum` and not directly by the enum `ColorE`. Whether that makes sense is debatable. – Peter - Reinstate Monica Mar 12 '17 at 07:48
  • @Yochai Timmer That makes sense! – javaLover Mar 12 '17 at 07:52