I want to have a static member a of a base class B, with the following features:
- It is a vector (likely not the "challenging" part).
- Derived classes
D1, etc., should be able to have similar static members, with different values. Not all the classes would have them, and if a classD2does not define it, its correspondingawould be the lowest in the parent hierarchy. - I want to access any of these members in any of the classes with a single function
getAdefined in the base class. E.g.,D1should be able to get its owna(or the lowest in the parent hierarchy, ifD1does not define it).
So far, the solutions I have seen require redefining getA in each derived class in the hierarchy (see below).
I want to avoid this for several reasons, e.g.,
I have a large hierarchy, so applying the required changes, and possible future changes (even if unlikely) become cumbersome.
Are there any alternatives to achieve my goal?
Related:
- Overriding static variables when subclassing
- https://forums.unrealengine.com/t/workaround-overriding-a-static-variable/91685/2
CodePudding user response:
No, you can't override member variables (static and non-static alike) - only virtual member functions.
the solutions I have seen require redefining
getAin each derived class
You would only need to override getA in the classes that should have a separate a.
Example:
struct B {
virtual std::vector<int>& getA() const {
static std::vector<int> a;
return a;
}
};
struct D1 : B {
std::vector<int>& getA() const override {
static std::vector<int> a;
return a;
}
};
struct D2 : B { // no need to override `getA` here - it'll use `B::getA`
};
CodePudding user response:
How about having a simple (non-static) virtual getter and the static var in that getter? As you said, you already have an instance, so you have access to the virtual table. To make it automatic, we might rely on the typical CRTP:
class Base {
public:
virtual const std::vector<int>& getA() = 0;
};
template<typename B, typename D>
class BaseImpl : public B {
public:
const std::vector<int>& getA() override { return D::static_var; };
};
class D1 : public BaseImpl<Base, D1>
{
public:
static const std::vector<int> static_var;
};
const std::vector<int> D1::static_var = {1};
class D2 : public D1 /* no static_var */
{
};
class D3 : public BaseImpl<D2, D3>
{
public:
static const std::vector<int> static_var;
};
const std::vector<int> D3::static_var = {1, 3};
You might even automate the detection of static_var if that's easier for you (via std::enable_if<> and is_detected<>).
