13

Possible Duplicate:
Overriding static variables when subclassing

I have a set of classes that are all derived from a base class. Any of these derived classes declare the same static variable. It is however specific to each of the derived classes.

Consider the following code.

class Base {
    // TODO: somehow declare a "virtual" static variable here?
    bool foo(int y) { 
        return x > y; // error: ‘x’ was not declared in this scope
    }
};

class A : public Base {
    static int x;
};

class B : public Base {
    static int x;
};

class C : public Base {
    static int x;
};

int A::x = 1;
int B::x = 3;
int C::x = 5;

int main() {}

In my base class I wanted to implement some logic, that requires the knowledge of the derived-class-specific x. Any of the derived classes has this variable. Therefore I would like to be able to refer to this variable at base class scope.

This wouldn't be a problem if it were a simple member variable. However, semantically, the variable is indeed not a property of the derived class' instance, but rather of the derived class itself. Therefore it should be a static variable.

UPDATE I need the class hierarchy to preserve its polymorphic nature. That is, all my derived class' instances need to be members of a common base class.

Then however, how can I get my hands on this variable from the base class method?

Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • 3
    Defining a virtual method `get_static_x()` in the base class and overriding it in every derived class would be one way. – jogojapan Oct 09 '12 at 09:15
  • Create getters on each derived will solve the problem? – PaperBirdMaster Oct 09 '12 at 09:16
  • Make base class Constructor to accept X and y . also make each derived class constructor to accept X. and then in each derived class write constructor like this " public DerivedClassConstructor(int x) : base(x) {} it will pass the supplied X to the base class constructor. – muhammad kashif Oct 09 '12 at 09:21
  • Maybe the issue is that you try to implement code sharing in a base class, so you're abusing the base class for implementation reuse instead of interface reuse. Consider not having the code in the base class in the first place but rather in a free function. – Frerich Raabe Oct 09 '12 at 09:36

2 Answers2

23

You can use the Curiously recurring template pattern.

// This is the real base class, preserving the polymorphic structure
class Base
{
};

// This is an intermediate base class to define the static variable
template<class Derived>
class BaseX : public Base
{
    // The example function in the original question
    bool foo(int y)
    { 
        return x > y;
    }

    inline static int x;
};

class Derived1 : public BaseX<Derived1>
{
};

class Derived2 : public BaseX<Derived2>
{
};

Now classes Derived1 and Derived2 will each have a static int x available via the intermediate base class! Also, Derived1 and Derived2 will both share common functionality via the absolute base class Base. Note: The variable declaration uses C++17's inline static member declaration to avoid the need for a separate template variable definition.

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
  • 1
    He doesn't _need to_ (Minion's answer is valid too) but this is certainly the best way! +1 – Lightness Races in Orbit Oct 09 '12 at 09:46
  • 1
    This doesn't work. As presented, at least, the different derived classes do not have a common base. – James Kanze Oct 09 '12 at 09:54
  • 1
    I've updated the example to include a common base. – Mark Ingram Oct 09 '12 at 10:00
  • -1 "need to" is incorrect. Also, the example code would not necessarily be technically incorrect after it's been fixed, but the whole concept is needlessly complicated for the job at hand - a Rube Goldberg solution. – Cheers and hth. - Alf Oct 09 '12 at 10:42
  • 2
    Fine, I've removed the "need to" words, although I still think you're being harsh. This solution is neater than the others presented below. – Mark Ingram Oct 09 '12 at 10:54
  • 1
    @Mark: for now I let the downvote stand. i see no neatness but i do see e.g. lacking definitions of `x` for each class. thus the example code, being rather incomplete, *looks* shorter and more simple than the more complete code of other answer – Cheers and hth. - Alf Oct 09 '12 at 18:52
  • Why do you need a definition of `x` for each class? It's in the BaseX class? As it uses CRTP you don't need to define it in each derived class. That's the point of using CRTP. – Mark Ingram Oct 10 '12 at 08:05
6

With a virtual getter function

class Base {
public:
    bool foo(int y) const{ 
        return getX() > y;
    }
    virtual int getX() const = 0;
};

class A : public Base {
    static const int x;
    int getX() const {return x;}
};

class B : public Base {
    static const int x;
    int getX() const {return x;}
};

class C : public Base {
    static const int x;
    int getX() const {return x;}
};

int A::x = 1;
int B::x = 3;
int C::x = 5;

int main()
{
    C c;
    bool b = c.foo(3);
}
Minion91
  • 1,911
  • 12
  • 19
  • +1 I prefer the CRTP approach (for neatness and performance) but this is valid too. – Lightness Races in Orbit Oct 09 '12 at 09:47
  • This requires OP to copy and paste the same variable in multiple classes, then use a virtual function to access a static variable! – Mark Ingram Oct 09 '12 at 10:14
  • the CRTP is sweet yes, didn't know that one. but for simplicity I like my solution aswel – Minion91 Oct 09 '12 at 10:24
  • +1 just for being in the right direction. the "get" name prefix is just visual noise, though. and with that getter declared `const`, `foo` and `b`, not to mention `x`!, should also be declared `const`. and what's those superfluous semicolons doing there? I think they're likely even syntactically invalid. Still, right direction. – Cheers and hth. - Alf Oct 09 '12 at 10:47
  • It went trough LWS, I don't get to do much in-lining at my job, so I wasn't certain about the syntax. foo and x should certainly be const, b depends a bit. – Minion91 Oct 09 '12 at 10:51