4

I have a rather strange situation where I would like to be able to define certain constants that a subclass of an ABC can override.

struct A {
    static const int a = 20;
    virtual int func() = 0;
};
struct B : public A {
    static const int a = 3;
    int func() { return 5; }
};
struct C : public A {
    static const int a = 4;
    int func() { return 3; }
};

Unfortunately, if I use A *aPtr = new B, aPtr->a will return 20, instead of 3.

One workaround I see is one-liner functions (along the lines of func in the above example), but the syntax of constants is quite a bit more appropriate for this particularly situation conceptually. Is there a syntactically reasonable way of resolving which constants to use at runtime, where the calling code doesn't need to know anything after initial object creation?

iammilind
  • 68,093
  • 33
  • 169
  • 336
jkerian
  • 16,497
  • 3
  • 46
  • 59
  • possible duplicate of [Overriding static variables when subclassing](http://stackoverflow.com/questions/594730/overriding-static-variables-when-subclassing) – 一二三 Sep 26 '11 at 10:01
  • 1
    The reasoning behind wanting this may be flawed: A constant is supposed to be, well, *constant*. It's not sometimes constant and sometimes something else. Similarly, static members are properties of classes, not instances, so they play no role in inheritance, which is an *instance*-based concept. – Kerrek SB Sep 26 '11 at 10:56

2 Answers2

8

Constants, especially static constants, cannot be overriden like you are asking for. You would have to use a virtual function instead:

struct A {
    virtual int get_a() { return 20; }
    int func() = 0;
};

struct B : public A {
    virtual int get_a() { return 3; }
    int func() { return 5; }
};

struct C : public A {
    virtual int get_a() { return 4; }
    int func() { return 3; }
};

Another option would be to use a template for the constant instead:

template< const int a_value = 20 >
struct A {
    static const int a = a_value;
    int func() = 0;
};

struct B : public A<3> {
    int func() { return 5; }
};

struct C : public A<4> {
    int func() { return 3; }
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 7
    For the templated version one should note that the classes `B` and `C` are now entirely unrelated, since they have different base classes. – Kerrek SB Sep 26 '11 at 10:58
2

You can get answer from the example itself ! :) Just declare a method like get_a() which is virtual and override the same.

struct A {
    static const int a = 20;
    virtual int get_a() const { return a; }  // <--- for A
};
struct B : public A {
    static const int a = 3;
    virtual int get_a() const { return a; }    // <--- for B
};
struct C : public A {
    static const int a = 4;
    virtual int get_a() const { return a; }    // <--- for C
};

Also note that, only method can be overridden in C++ and not the variables.

iammilind
  • 68,093
  • 33
  • 169
  • 336