重写非常量虚拟方法是否会隐藏常量重载?
考虑一下:(
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "A::f" << endl; }
virtual void f() const { cout << "A::f const" << endl; }
};
struct B : public A {};
struct C : public A {
virtual void f() { cout << "C::f" << endl; }
};
int main()
{
const B b;
b.f(); // prints "A::f const"
const C c;
c.f();
// Compile-time error: passing ‘const C’ as ‘this’ argument of
// ‘virtual void C::f()’ discards qualifiers
}
我正在使用 GCC。)
所以看起来 f() 的 const 版本隐藏在 C 中。这对我来说很有意义,但它是标准强制要求的吗?
Consider:
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "A::f" << endl; }
virtual void f() const { cout << "A::f const" << endl; }
};
struct B : public A {};
struct C : public A {
virtual void f() { cout << "C::f" << endl; }
};
int main()
{
const B b;
b.f(); // prints "A::f const"
const C c;
c.f();
// Compile-time error: passing ‘const C’ as ‘this’ argument of
// ‘virtual void C::f()’ discards qualifiers
}
(I'm using GCC.)
So it seems that the const version of f() gets hidden in C. This makes a lot of sense to me, but is it mandated by the standard?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我将(再次)链接这篇精彩的文章:
所以,是的,
f
的const
版本是隐藏的,这是完全正常的。正如 Simone 所指出的,您可以使用using
语句将A::f
引入C
范围。I will (once more) link this great article :
So yes, the
const
version off
is hidden, and that's perfectly normal. As pointed out by Simone, you can use ausing
statement to bringA::f
inC
scope.是的。你可以这样写:
让你的代码编译:
有关更多信息,你可以参考 2010 C++ 草案文档(你可以找到 此处)第 10.2 章(3-4)。
Yes, it is. You may write:
to make your code compile:
For more infos, you can refer to the 2010 C++ draft document's (which you can find here) chapter 10.2.(3-4).
隐藏基本成员的不是虚拟性或常量性(或缺乏),任何派生方法都会隐藏同名的基本方法。这样做是为了改善脆弱的基础阶级问题。
想象一下您的代码按如下方式工作(可能多年),删除了不相关的部分:
然后您需要修改 Base 以包含一个执行完全不同操作的方法,但是由于某种原因,您想将其命名为“f” :
如果没有这条规则,每次派生调用 f 的使用都需要手动评估 - 如果 Base 位于提供给其他人的库中,您甚至可能无法访问这些其他用途!面对用户定义的(隐式)转换,情况会变得更糟。
相反,我们决定要求派生类明确声明它们希望使用 using 声明从 Base 导入给定名称。这条规则可能会令人惊讶,我不确定这对今天的语言是否有净好处,但他们没有问我——无论如何,当时我可能只能用两个音节的单词来回答他们。 :)
It is not the virtuality or const-ness (or lack thereof) that hides the base member, any derived method hides a base method of the same name. This was done to ameliorate the fragile base class problem.
Imagine your code was working (possibly for years) as below, with non-relevant parts removed:
Then you need to modify Base to include a method that does something completely different, but, for some reason, you want to name it 'f':
Without this rule, every use of a Derived calling f needs to be manually evaluated — and if Base is in a library given to other people, you may not even have access to those other uses! It gets worse in the face of user-defined (implicit) conversions.
Instead, it was decided to require derived classes to explicitly state they want to import given names from Base with a using declaration. This rule can be surprising and I'm not sure it's a net benefit to the language today, but they didn't ask me — at the time, I could probably only have answered them with two-syllable words, anyway. :)
插入
using B::f;
C++ 标准 2003. 13.2 p.1:
因此
C::f
隐藏了所有A::f
。Insert
using B::f;
C++ Standard 2003. 13.2 p.1:
Thus
C::f
hides allA::f
.