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

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关键字,因为

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

virtual关键字应该添加到基类的函数中,以使它们可重写。在您的示例中,结构体A是基类。虚指的是在派生类中使用这些函数。然而,如果你想要你的派生类本身也是基类,你想要那个函数是可重写的,那么你就必须把虚函数放在那里。

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

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

这里C继承自B,所以B不是基类(它也是一个派生类),C是派生类。 继承图如下所示:

A
^
|
B
^
|
C

所以你应该把虚函数放在可能有子基类的函数前面。Virtual允许你的孩子覆盖你的函数。将虚函数放在派生类中的函数前面并没有错,但这不是必需的。尽管如此,还是建议这样做,因为如果有人想从你的派生类继承,他们会不高兴方法重写没有像预期的那样工作。

因此,在所有涉及继承的类中,将virtual放在函数前面,除非您确定该类不会有任何需要重写基类函数的子类。这是很好的练习。