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 classD2
does not define it, its correspondinga
would be the lowest in the parent hierarchy. - I want to access any of these members in any of the classes with a single function
getA
defined in the base class. E.g.,D1
should be able to get its owna
(or the lowest in the parent hierarchy, ifD1
does 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
getA
in 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<>
).