Consider the following class hierarchy. Concrete templated class A, templated abstract class B and an interface C, with A <-- B <-- C
. Consider that B has a function declaration
virtual std::optional<T> foo() const = 0;
and c has a function declaration
virtual bar() = 0;
both of which are defined in A appropriately.
There exists somewhere in the code a list of objects B, over which we call foo()
, and there exists a list of C* pointers over which we call bar()
.
For a minimal example:
class A <typename T> : public B <T>
{
public:
std::optional<T> foo() const override { /*...*/ };
bar() override { /*...*/ };
// ...
};
class B <typename T> : public C
{
public:
virtual std::optional<T> foo() const = 0;
// ...
}
class C
{
public:
virtual bar() = 0;
}
The issue I am having is that I want to add a boolean state over this small hierarchy. Particularly, I have the following requirements
m_isInteresting
over the object represented by this hierarchy.m_isInteresting
state it to be in A (for decoupling reasons).foo()
to set m_isInteresting = true;
.bar()
to set m_isInteresting = false;
.How can I achieve this?
m_isInteresting
member and the appropriate accessors, with a method forward of bar()
, in which I call C's bar()
function and set the class member m_isInteresting
to false, but then I can't set the member to true because foo()
is down the class hierarchy.foo()
's declaration to C (while keeping it's definition in A), but this is very difficult because the function returns a std::optional<T>
and well, C is not templated; a derived class's function signature must match that of the base class.m_isInteresting
shared between them, but held externally, but this is getting ugly and complicated.There must be something that I am missing here.
The below code fulfils your requirements. You can put m_isInteresting
inside the C
class and mark it protected for the subclasses to be able to access it. You can then refer to it as this->m_isInteresting
in the subclasses.
#include "optional"
class C {
protected:
bool m_isInteresting = false;
public:
virtual void bar() = 0;
};
template <typename T>
class B: public C {
public:
virtual std::optional<T> foo() = 0;
};
template <typename T>
class A: public B<T> {
public:
std::optional<T> foo() override {
this->m_isInteresting = true;
return {};
}
void bar() override {
this->m_isInteresting = false;
}
};