1

I want static variables in derived classes, so I want to make some stuff in a base class. Base class would be virtual. Is it possible?

class Base {
public:
    static const int x;
    void f() {
        return x;
    }
    virtual void g() = 0;
};

class Derived1 : virtual Base {
public:
    void g() {}
};
const int Derived1::x = 1;

class Derived2 : virtual Base {
public:
    void g() {}
};
const int Derived2::x = 2;

...

Derived1 a;
Derived2 b;
a.f() == 1; // should be true
b.f() == 2; // should be true
J. S.
  • 425
  • 4
  • 13

2 Answers2

1

Alas, no, C++ has no virtual statics. What you can do instead is use a non-static getter method:

 class A {
      virtual const int& Foo() const = 0;
 }

 class B : A {
      static int foo_;
      const int& Foo() const override { return foo_; }
 }
 int B::foo_ { 1 };

You can "automate" this with a mix-in class defined using CRTP:

 class A {
      virtual const int& Foo() const = 0;
 }

 template <typename T>
 class FooHolder {
      static int foo_;
      const int& Foo() const override { return foo_; }
 }

 class B : A, virtual FooHolder<B> {
      // other stuff
 }

This way, the only thing you need to do in a subclass is also indicate the mix-in inheritance. There might be some virtual inheritance caveats I'm missing here (as I rarely use it).

Another option, described here, is to make class A templated itself, so that each B inherits from a different A. But that will break your inheritance structure.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
1

C++ has no notion of virtual member variables -- static or regular. It has virtual member functions.

It will be best to encapsulate the static member variables and access them through virtual member functions.

class Base {
public:
    // static const int x;

    void f() {
       int x = getX();
       // Use x
    }

    virtual int getX() = 0;
    virtual void g() = 0;
};

class Derived1 : virtual Base {
  static const int x;
  public:
    virtual int getX() { return x;}
    void g() {}
};
const int Derived1::x = 1;

Unless there is another compelling reason to keep Derived1::x as a member variable, you can remove it and simplify Derived1.

class Derived1 : virtual Base {
  public:
    virtual int getX() { return 1;}
    void g() {}
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270