看起来将虚方法声明为私有可以很好地分离以下两种客户端的接口:
- 实例化对象并调用该方法的客户端
- 从该类派生并可能想要重写该方法的客户端
简单地说,第一个客户端不需要知道一个方法是否是虚方法。他将调用基类公共非虚方法,而该方法将调用私有虚方法。例如,请参见下面的代码。
现在,在虚方法需要超级传递其基类相应虚方法的情况下,比如说一个保存方法——它必须通过继承链中的所有虚方法才能保存对应于每个派生级别的数据——我们别无选择,只能使用保护虚方法。除非有一种方法可以保证在不使用超级消息传递的情况下在所有派生级别上保存数据(我不知道这种方法)。
我想知道上述推理是否正确。
确保使用滚动条查看整个代码。
#include <iostream>
using namespace std;
class A {
string data;
protected:
virtual void SaveData()= 0;
public:
A():data("Data of A"){}
void Save(){
cout << data << endl;
SaveData();
}
};
class B : public A {
string data;
protected:
virtual void SaveData() { cout << data << endl;}
public:
B():data("Data of B") {}
};
class C : public B {
string data;
protected:
virtual void SaveData() {
B::SaveData();
cout << data << endl;
}
public:
C():data("Data of C") {}
};
int main(int argc, const char * argv[])
{
C c;
c.Save();
return 0;
}
public
时的含义。除了将客户端(public)接口与实现(非public)接口分开的指导方针外,我看不出为什么公共虚方法会阻止NVI的工作。在上面的例子中声明saveImpl()为public是否会造成灾难? - RichsaveImpl
被声明为final
(因此不再是虚函数),所以不需要:) - Matthieu M.final
部分。但是你的解决方案特别适用于OP想要的内容,即在每个派生级别上强制传播和处理。在传统的NVI习语中,任何派生类都可以覆盖saveImpl
,为什么saveImpl
不能是公共的,除非它违反了面向对象原则,即将接口与实现分离。 - Rich