是否建议明确地使重写功能虚拟?

在C ++ 11之前,在派生类中重写虚拟函数之前,建议将virtual关键字也添加到派生类函数中,以使意图清晰。

现在这样的功能被标记为“覆盖”,其中包括必须有虚拟基本功能的概念。 因此,我现在宁愿忽略虚拟:

class Derived: public Base {
public:
  void Overriden() override;
  // Instead of: virtual void Overriden() override;
};

但是,这会导致MSVC 2012中出现智能感知错误:“覆盖”修饰符需要虚拟函数声明并带有明确的“虚拟”关键字

编译器显然编译这个类,但是这个错误让我想到了它。 是否仍然有充分的理由添加虚拟关键字?


我认为这更多的是品味的问题:-)

我更喜欢在定义后面写入重写,这意味着函数已经是虚拟的。 程序员是懒惰的定义,所以保持源代码简洁:-)

我们在我们的编码准则中添加了一条规则,在正常的更改过程中或在重构实际的类时,必须覆盖重写,并且应该从旧代码中删除虚拟。

但这只是我们的解决方案,没有技术上的理由!


正如在override关键字的文档中所报告的那样,其含义是手头的函数必须覆盖一个虚函数:

在方法声明中,覆盖指定函数必须重写基类方法。

这是执行(即使编译器强制执行)这种要求的一种手段。 当然,如果基类的函数不是虚拟的,代码将不会编译。 因此,正如你所指出的那样,添加虚拟是多余的。

我认为在c ++ 11之前添加它并不是一个好建议。 考虑一下这段代码:

#include <iostream>

using namespace std;

class A{
    public:
    void f(){
        cout << "A" << endl;
    }
};

class B : public A{
    public:
    virtual void f(){
        cout << "B" << endl;
    };
};

class C : public B{
    public:
    void f(){
        cout << "C" << endl;
    };
};

int main( int argc, char* argv[] ) 
{
    C c;
    A& aref = c;
    aref.f();
    B& bref = c;
    bref.f();
}

其输出显然是“A”,后面是“C”。 如您所见,在class C添加virtual根本没有任何作用,而class B virtual中扮演关键角色。 针对向class C添加virtual的惯例会使得难以一目了然。


是的,在重写基类行为时,您应该更喜欢使用override而不是virtual 。 因为它可能导致可能的错误

这怎么可能导致错误? 这是一个例子,

#include <iostream>
using namespace std;

class Base {
 public:
    virtual void foo() {
        std::cout << "BASE foo" << std::endl;
    }
    void bar() {
        std::cout << "BASE bar" << std::endl;
    }
};


class A : public Base{
 public:
    void foo() override {
        std::cout << "A foo" << std::endl;
    }
    virtual void bar() { 
        std::cout << "A bar" << std::endl;
    }
};

class B : public A {
 public:
    void bar() override { 
        std::cout << "B bar" << std::endl;
    }
};


int main(int argc, char *argv[])
{
    B b;
    A *a = &b;
    Base *base = &b;
    base->foo();
    a->foo();
    base->bar();
    a->bar();
    return 0;
}

而输出将是

A foo
A foo
BASE bar
B bar

foo()会被正确覆盖,但bar在某些情况下不会被隐藏。 即使底层对象相同,对bar()的调用也不会调用相同的方法

如果我们强制自己总是在override时使用override ,并且只在virtual中定义新的虚函数,那么当我们尝试void bar() override {} ,编译器会error: 'void A::bar()' marked 'override', but does not override

这正是Autosar规范定义以下规则的原因

规则A10-3-1(要求,实现,自动化)虚拟函数声明应包含三个指定符中的一个:(1)虚拟,(2)覆盖,(3)最终。

理由:指定这三个说明符中的多个以及虚拟函数声明是多余的,并且是潜在的错误来源。

链接地址: http://www.djcxy.com/p/15855.html

上一篇: Is it recommended to explicitly make overriding functions virtual?

下一篇: Beginning of Project