C++样式:将虚拟关键字前缀为重写方法

ery*_*ydo 25 c++ methods coding-style virtual-functions

我一直在与我的同事讨论是否使用virtual关键字为重写方法添加前缀,或者仅在原始基类中添加前缀.

我倾向于使用virtual关键字为所有虚拟方法(即涉及vtable查找的方法)添加前缀.我的理由是三重的:

  1. 鉴于C++缺少override关键字,virtual关键字的存在至少会通知您该方法涉及查找,理论上可以通过进一步的特化来覆盖,或者可以通过指向更高基类的指针来调用.

  2. 始终使用这种风格意味着,当你没有virtual关键字看到(在我们的代码至少)的方法,你可以初步认为它既不是从基础衍生也不专门的子类.

  3. 如果,通过一些错误,虚拟从IFoo中删除,所有子节点仍将起作用(CFooSpecialization :: DoBar仍会覆盖CFooBase :: DoBar,而不是简单地隐藏它).

正如我所理解的那样,反对这种做法的论点是,"但这种方法不是虚拟的"(我认为这种方法无效,并且来自对虚拟性的误解),并且"当我看到虚拟关键字时,我希望意味着有人从中衍生出来,然后去寻找它们."

假设的类可以分布在几个文件中,并且有几个专门化.

class IFoo {
public:
    virtual void DoBar() = 0;
    void DoBaz();
};

class CFooBase : public IFoo {
public:
    virtual void DoBar(); // Default implementation
    void DoZap();
};


class CFooSpecialization : public CFooBase {
public:
    virtual void DoBar(); // Specialized implementation
};
Run Code Online (Sandbox Code Playgroud)

从风格上讲,你会从两个派生类中删除虚拟关键字吗?如果是这样,为什么?Stack Overflow的想法是什么?

Tyl*_*nry 23

我完全同意你的理由.这是一个很好的提醒,该方法在调用时将具有动态调度语义.你的同事正在使用的"那种方法不是虚拟的"论点完全是假的.他把虚拟和纯虚的概念混为一谈.


Abh*_*hay 6

一个虚拟的函数永远是虚拟的.

因此,在任何情况下,如果虚拟关键字未在后续类中使用,则不会阻止函数/方法"虚拟",即被覆盖.所以我参与的其中一个项目有以下指南,我有点喜欢:

  • 如果应该覆盖函数/方法,请始终使用'virtual'关键字.在接口/基类中使用时尤其如此.
  • 如果派生类应该是子类,则进一步明确说明可以覆盖的每个函数/方法的'virtual'关键字.C++ 11使用'override'关键字
  • 如果派生类中的函数/方法不应该再次被子类化,那么关键字"虚拟"将被注释,表示该函数/方法被覆盖但没有其他类再次覆盖它.这个过程不会阻止某人覆盖派生类,除非该类是最终的(不可派生的),但它表明该方法不应该被覆盖.例如:/*virtual*/ void guiFocusEvent(); C++ 11,使用'final'关键字和'override'Ex:void guiFocusEvent() override final;