您真正想要的是最有可能使用所谓的模板方法模式将公共接口与继承的实现细节分开。
您的公共接口应该使用非虚拟方法。虚拟方法都应该是私有的。然后基类中的接口可以强制执行不变量并进行样板工作。派生类仍然可以覆盖虚拟方法,只是不能直接调用它。
只有当派生类需要调用虚方法的基实现时,才使虚方法受到保护。这几乎是全部。
基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。前者当您希望使用基类接口执行销毁时。现在这就是全部:)
具体来说:
#include <iostream>
#include <cassert>
using namespace std;
class A
{
// we do magic without sprinking any dust, but optionally we could sprinkle some beforehand
void virtual sprinkle() {};
void virtual magic(int) = 0;
public:
void doSomeMagic(int power) {
assert(power > 3 and power < 8);
sprinkle();
magic(power);
}
virtual ~A() {}
};
class B: public A
{
void magic(int power) {
cout << "B: did magic of with power=" << power << endl;
}
};
class C : public B
{
void sprinkle() {
cout << "C: also sprinked some dust before doing the magic" << endl;
}
};
int main()
{
B b;
C c;
b.doSomeMagic(5);
c.doSomeMagic(6);
return 0;
}
B: did magic of with power=5
C: also sprinked some dust before doing the magic
B: did magic of with power=6