使用下面给出的结构定义…

struct A {
    virtual void hello() = 0;
};

方法# 1:

struct B : public A {
    virtual void hello() { ... }
};

方法# 2:

struct B : public A {
    void hello() { ... }
};

这两种重写hello函数的方法有什么区别吗?


当前回答

函数的“虚拟性”是隐式传播的,但是如果没有显式使用virtual关键字,我使用的至少一个编译器会生成警告,所以如果只是为了让编译器保持安静,你可能想使用它。

从纯粹的风格角度来看,包括virtual关键字清楚地向用户“宣传”这个功能是虚拟的。这对任何进一步子类化B而不必检查A的定义的人都很重要。对于深层类层次结构,这变得尤为重要。

其他回答

它们完全一样。它们之间没有什么区别,只是第一种方法需要更多的输入,而且可能更清楚。

对于编译器来说,无论在派生类中编写虚函数还是省略它都没有区别。

但是您需要查看基类来获得此信息。因此,我建议在派生类中也添加virtual关键字,如果您想向人类显示该函数是虚的。

不需要,派生类的虚函数重写上的virtual关键字不是必需的。但是值得一提的是一个相关的缺陷:无法覆盖虚函数。

如果您打算重写派生类中的虚函数,但在签名中犯了错误,从而声明了一个新的不同的虚函数,则会发生重写失败。此函数可能是基类函数的重载,也可能在名称上不同。无论是否在派生类函数声明中使用virtual关键字,编译器都无法判断您打算重写基类中的函数。

然而,谢天谢地,c++ 11显式重写语言特性解决了这个缺陷,它允许源代码清楚地指定一个成员函数用于重写基类函数:

struct Base {
    virtual void some_func(float);
};

struct Derived : Base {
    virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};

编译器将发出编译时错误,编程错误将立即显现(也许Derived中的函数应该将float作为参数)。

参考WP: c++ 11。

在派生类中不需要virtual关键字。下面是c++标准草案(N3337)的支持文档(强调我):

10.3虚函数 如果虚成员函数vf在类Base和类Derived(直接或间接从Base派生)中声明,则声明了一个与Base::vf同名、形参类型-list(8.3.5)、cv- qualifier和ref-qualifier(或没有相同)的成员函数vf,则Derived::vf也是虚函数(无论是否这样声明),并且它覆盖Base::vf。

我肯定会为子类包含Virtual关键字,因为

我,可读性。 2这个子类可以向下派生,你不希望派生类的构造函数调用这个虚函数。