Charles
Charles

Reputation: 1239

Require derived classes to provide a static const value

I have a base class and derived classes. The base class uses pure virtual methods to require the derived classes to implement methods - otherwise it doesn't compile. Classic.

Can I also require from the base class that the derived classes give a value for a constant ? It has to be a compile-time constant, but also it has to be a compilation error if they don't give a value for the constant. It is also static to each derived class since it is instance-independent.

I have seen answers suggesting to write a pure virtual getter which returns a value, but the getter could then have dynamic code with changing behavior depending on some conditions. I really mean this to be a lifelong constant. Also, since it's not static in that solution, there might be one instance of that constant value for each instance of the derived classes, and that's a waste of memory.

Basically like a name or id. Here is what it would sort of look like, but of course that doesn't compile for multiple reasons.

class Base
{
     Base();
    ~Base();
     virtual void doSomething() = 0;
     /* Unknown for Base, meant as an abstract / pure virtual class,
        but required for all derived classes. */
     static const int id;
}

class VariantA : public Base
{
    VariantA();
    ~VariantA();

    static const int id = 215684;
    void doSomething() {...}
    SomeType someData;
};

class VariantB : public Base
{
    VariantB();
    ~VariantB();

    static const int id = 6451322;

    void doSomething() {... /* do it differently than VariantA */}
    
    SomeOtherType someOtherData;
};

id never changes and does not depend on the instance, but does depend on which derived class we are handling at any given moment. Simply having an object of a class that inherits from Base guarantees that we have such a thing as id, however the value varies, not depending on the object as an instance, but simply on the class of the object.

Upvotes: -2

Views: 154

Answers (1)

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14673

Within these constraints you cannot do better than a virtual getter (which means run-time):

struct Base {
          enum { idN = 0 };
          virtual int id() { return idN; }
};

struct Derived : Base {
          enum { idN = Base::idN + 1 };
          int id() override { return idN; } // note: it's actually  Derived::idN
};

If that is meant for use only inside of a base class implementation,the very idea is a sign of flawed design - something is becoming a "god class" there. You rather should do behaviour injection. As your concern is used memory I sugges to look at Flyweight pattern, perhaps it's what you actually need instead of managing individual "small objects".

Upvotes: 1

Related Questions