How to Emulate the “super” Keyword in C++
fluentcpp.com
fluentcpp.com
As others have pointed out, putting the keyword in the base class is Highly Questionable.
I've also seen inconsistency in various inheritance diagrams; sometimes the arrow points to the child, sometimes to the parent.
On the other hand, there's nothing wrong with "super", given that it stands for "superclass", which has a well-defined meaning. For that matter, so does "base class".
class A {};
class B : public A {};
class C : public B {};
Using the convention of defining `base_type` in the base class means that C will expect B to define `base_type`, which means that B will be cut off from A's `base_type`. This then forces you to use different identifiers, which brings you back to square one (you might as well just explicitly write out the class in that case).Not exactly, since C's constructor does not call A's directly. (On the other hand, base_class::base_class might just do the trick.)
When you write the code, it feels a bit cumbersome. When you read it, though, you know exactly what’s going on—which pays over and over again. These days, for most code in any language, I’m more inclined to say to myself “suck it up and be explicit” when it comes to these small decisions—as long as “explicit” doesn’t get confused with “needlessly long-winded”, of course.
To the extent that I have control over the architecture, I prefer flat hierarchies with pure virtuals and final implementations, but what are good approaches to solving this issue for deeper class hierarchies? Is there a good alternative to the pseudo Super if Class A, B, C, and D each need to twiddle some state when you call ::Foo() on an object of type E?
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);
}
};
Repeat for C and D.But I think C++ has what... parameter lists for that?
base_type::draw()
analogous to Java's super.draw()