有没有使用公共虚拟方法的正当理由?

时间:2014-03-24 06:44:55

标签: c++ c++11 polymorphism

有没有使用公共虚拟方法的正当理由?

我已经读过某个地方,我们应该避免使用公共虚拟方法,但我想向专家确认这是否是有效的声明?

3 个答案:

答案 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();
    }

创建两级虚拟函数非常便宜,并为您提供了一个附加层,使您可以轻松控制将来调用虚方法的方式。