有没有使用公共虚拟方法的正当理由?
我已经读过某个地方,我们应该避免使用公共虚拟方法,但我想向专家确认这是否是有效的声明?
答案 0 :(得分:7)
为了获得良好稳定的API设计,非虚拟接口是一个很好的习惯用法。
我将按照现有的优秀文献推荐:
另见这些精彩的答案:
(Sumant Tambe在他的博客上有一个有趣的Design Intent Implications矩阵,其中有一些关于设计意图的内容。)
答案 1 :(得分:5)
使virtual
函数非公共允许基类围绕它们创建协议。如果没有别的,这可以用于需要仅基类的检测的一些会计/分析。基类公共接口可以是仅仅转发到inline
函数的virtual
函数。遗憾的是,派生类可以放宽限制,即派生类可以从基类中公开访问virtual
函数。
制作virtual
函数protected
实际上还有另一个重要原因:当重载virtual
个函数(例如do_put()
中的std::num_put<...>
成员)时,它是当覆盖其中一个功能时,容易意外隐藏其他重载。当virtual
函数既是自定义点又是调用接口时,这很容易导致令人惊讶的行为。当virtual
函数为protected
时,很明显调用接口和自定义接口实际上是不同的,即使直接使用派生类也避免了问题。 virtual
函数可能希望protected
允许重写函数从基类调用默认实现。如果没有默认实现,virtual
函数也可以是private
。
这个答案讨论了为什么virtual
函数不应该是public
。你是否应该首先拥有virtual
个函数是一个单独的问题,并且有一些不平凡的答案。
答案 2 :(得分:1)
我想到了一件事 - 不使用公共虚方法简化了类的接口与实现的分离。比如,你提供了一个公共方法做某事:
public:
virtual void DoSth()
{
}
在一段时间后引入了一个更改,这需要在执行某些操作之前初始化并完成基类。如果您已从类中派生了几个类,则必须更改其实现。但是如果你用以下方式写的话:
protected:
virtual void InternalDoSth()
{
}
public:
void DoSth()
{
InternalDoSth();
}
这只是改变DoSth实施的问题:
public:
void DoSth()
{
InitializeSth();
InternalDoSth();
FinalizeSth();
}
创建两级虚拟函数非常便宜,并为您提供了一个附加层,使您可以轻松控制将来调用虚方法的方式。