《Effective C++》35:考虑virtual函数以外的其他选择
1、借由 Non-Virtual Interface(NVI) 手法实现 Template Method 模式
NVI手法将虚函数作为private的,然后用非虚函数作为接口来调用这个虚函数。这样就把虚函数封装起来了。
如:
//令客户通过调用public的非虚函数间接地调用private的虚函数。
class Widget
{
public:
//这种作为虚函数与外界的交接的函数,被Scott Meyers称为virtual函数的外覆器(wrapper)
void Draw() //派生类不重新定义这个函数
{
... // Do something...
DoDraw();
... // Do something...
}
private:
virtual void DoDraw() //派生类可以重新定义这个函数
{
...... //缺省的内容
}
};
另外,加上private的虚函数的一个测试:
// Rule35:考虑virtual函数以外的其他选择
#include <iostream>
#include <string>
using namespace std;
class B
{
private:
virtual void DoShow()
{
cout << "I'm a Base." << endl;
}
public:
void Show()
{
DoShow();
}
};
class D : public B
{
private:
virtual void DoShow()
{
cout << "I'm a Derive." << endl;
}
};
int main()
{
D d;
d.Show();
B* p = new D;
p->Show();
B b;
b.Show();
return 0;
}
运行结果: 对于上述结果,《Effective C++》上有这样的解释:“重新定义函数”表示解释某些事“怎么”完成,而“调用函数”则表示它“何时”被完成。
这些事都是各自独立互不相干的。因此私有的virtual函数可以在子类中被重写,而不可以在子类中被调用。
2、借由 Function Pointers 实现Strategy模式