当我重载一个C++函数时,是否需要再次指定“virtual”关键字?

16

当我重载一个虚函数时:

class Geoff
{
 public:
  virtual int getArea() { return 0; }
}

当我重写一个函数时,是否需要再次指定为“virtual”关键字?这样做有什么不同吗?我知道这两种方式似乎都可以正常工作,只是想知道其中是否还有其他的区别。

class George : public Geoff
{
 public:
  virtual int getArea() { return x*y; }
}

这不是重复,但确实有关联。 - Steven Sudit
@一二三:这是一个不太适合作为重复问题的候选,因为它实际上询问的是在不使用虚拟关键字的情况下是否可以“替换”函数(好答案会解释隐藏和虚拟分派之间的区别)。 - Tony Delroy
1
@TonyD - 你看,这是一场比赛,谁先通过编辑将问题变成另外一种形式或者让问题被关闭,谁就赢了。;-P - Derf Skren
1
如果它被关闭为那个问题的重复,我会重新打开它。 - Steven Sudit
2个回答

26
如果你使用C++11,应该使用override而不是virtual来重载虚函数,因为它既可以说明你正在重载一个虚函数,又可以检查是否存在可重载的基本匹配虚函数。
int getArea() override { return x*y; }
在C++03中,这是一个风格选择 - 如果你觉得它增加了文档价值,就把virtual放在里面。
在C++03中,这是一种风格选择——如果您认为它增加了文档价值,则将virtual放置其中。

2
你也可以使用 final 来防止进一步的覆盖,这使得编译器更容易地将调用该成员函数的虚拟化。 - Jon Purdy
1
我认为如果你知道GEORGE将被扩展,那么就在它前面加上virtual关键字。这是为了更好的理解。 - Syed Mauze Rehan
1
@Al-mo,很抱歉,但那是错误的建议。 "override" 已经足够清楚地表明该方法是虚拟的。 - Steven Sudit
1
对不起@Steven Sudit,那是针对问题中提供的代码,而不是这个答案。 - Syed Mauze Rehan

7
不,使用override。(http://en.cppreference.com/w/cpp/language/override
它的优点是如果父类中的方法不是虚函数,则会出现错误。 编辑 正如Mark指出的那样,如果签名不匹配,它也会失败,而虚函数则会默默地“成功”。引号内因为签名不匹配会隐藏基类中的方法,并创建一个不相关的新虚拟方法。

1
它还会检查覆盖方法是否具有与被覆盖方法兼容的签名(确实覆盖了该方法)。 - Mark Garcia
@MarkGarcia 这是真的,也是一个很好的观点,因为你不想在尝试覆盖时意外地过载。 - Steven Sudit
谢谢,重写仍然会在VS2010中为我生成一个警告,所以我将不得不与我们的架构师一起研究这个问题。 - Derf Skren
@DerfSkren VS2010不是一个很好的C++编译器,但它支持override。请查看http://msdn.microsoft.com/en-us/library/41w3sh1c.aspx。 - Steven Sudit
我想到你可能试图将override放在前面而不是最后。看一下我上面链接的例子,你就会明白我的意思。 - Steven Sudit
不,根据VS2010编译器的定义,它被视为“非标准扩展”:http://msdn.microsoft.com/en-us/library/ms173703%28v=vs.100%29.aspx - Derf Skren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接