覆盖非虚函数

31

C++11 FDIS指出:

如果一个虚函数被标记为override关键字,但它并没有覆盖其基类中的任何成员函数,则程序将会是非法的。[例如:

struct B {
    virtual void f(int);
};
struct D : B {
    void f(long) override; // error: wrong signature overriding B::f
    void f(int) override; // OK
};
如果`B::f`没有被标记为虚拟的话,那会怎样呢?那么程序是否非法?或者`override`会被忽略吗?我在标准文本中找不到对这种情况的处理方法。
更新1/2(已合并):我向C++编辑请求调查此事。感谢Johannes指出这一点。
- “void f(long) override”不会覆盖一个函数,特别是没有虚函数, - 所以它不是虚函数 - 因此,“如果一个虚函数被标记为…”这段文字不适用 - 因此,示例与文本不匹配。
但是通过意识到这一点,我发现“override”上下文关键字的意图无法实现:如果在函数名称中有拼写错误或参数类型错误使得函数本身不是虚函数,则标准文本永远不适用--并且“override”变得无用。
最好的解决方案可能是将虚拟放在示例函数的前面。

B中只有一个,不是D。 - towi
2
你在更新的答案中提出的问题已经被9.2p9解决了(请参见已接受答案的评论部分)。9.2p9禁止在非虚函数上使用“override”。我唯一看到的问题是示例,只需在“D”中的函数“f”之前加上“virtual”即可解决。 - Johannes Schaub - litb
3个回答

33

如果B::f没有被标记为虚拟的,那么程序是否不合法?

是的,程序就会不合法。因为要想覆盖(override)某个函数,这个函数必须被声明为虚拟的,否则不是覆盖(overriding),而是隐藏(hiding)。所以,你问题中的引用表明答案是肯定的。


2
你能提供一个标准的参考资料吗? - Mark B
1
我不同意:我引用的表述并没有对“非虚拟函数”做出任何说明。只有例子中才有。有趣的是,void D::f(long);本身不是 虚拟的,因为它没有覆盖virtual void B::f(int)。因此,引用的文本不适用于在D::f(long)后面添加override。这就是我感到困惑的原因... - towi
1
@towi:引用说:如果标记为虚拟的函数没有覆盖……那么程序是不合法的。术语“覆盖”只能应用于虚拟函数,因此,如果与您的新函数的签名相同的函数不是虚拟的,则此新函数不会覆盖它,因此引用适用。 - Armen Tsirunyan
1
啊,等等,我刚刚注意到@towi也有这些见解。当然,这个被接受的答案的推理是有缺陷的(规范对该段落的示例也有缺陷)。9.2p9拒绝了这个示例,而不是引用的文本。 - Johannes Schaub - litb
1
@Johannes:我不明白你在说什么!在函数上放置override并不会使其成为虚函数,我同意这一点。但我没有说过其他的事情。我是说如果基类中的函数不是虚函数,那么你就无法覆盖它,这意味着如果你在任何你认为覆盖了基类函数的函数上放置override关键字,你将得到一个非法程序。 - Armen Tsirunyan
显示剩余8条评论

0
如果 B:f 不是虚函数,那么 两个 D:f 函数都将是不合法的。

为什么?我引用的文本只涉及“虚函数”。如果B::f不是虚函数,则该文本不适用。 - towi
@towi 这段文字实际上是在提到 D::f,而不是 B::f。函数 D::f 仍然是虚函数,但试图覆盖一个不再是虚函数的函数 B::f,因此两个 D::f 函数都是不合法的。 - Branko Dimitrijevic

0

是的,当在任何非虚函数中添加override时,程序就会出现问题。

一般来说,具有不同签名(重载)的函数与具有不同名称的函数一样不同。规范中给出的示例并不意味着函数名称会影响override。它旨在展示override旨在防止的常见错误。


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