Though this is not the only solution, a visitor pattern seems to match.
I can think of other possibilities; hopefully this sparks some good ideas for you. I'll sketch up how I think the visitor pattern could work, sorry if it's already obvious:
Base class A. Derived classes B, C, and D.
When A::Foo() is called run code from each class, in the order they are initialized.
class A {
protected:
vector<function<void(int)>> visitFoo;
public:
void Foo(int bar) {
for (auto fn : visitFoo) {
fn(bar);
}
}
};
class B : public A {
protected:
// Do not override Foo in class B, C, or D.
void FooB(int bar) {
}
public:
B() {
// visitor pattern
visitFoo.emplace_back(FooB);
}
};
I can think of other possibilities; hopefully this sparks some good ideas for you. I'll sketch up how I think the visitor pattern could work, sorry if it's already obvious:
Base class A. Derived classes B, C, and D.
When A::Foo() is called run code from each class, in the order they are initialized.
Repeat for C and D.