[英]Does overriding a non-const virtual method hide a const overload?
考虑:
#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语言中。这对我来说很有意义,但它是否受标准规定?
我将(再次)链接这篇伟大的文章 :
首先,[编译器]查看直接范围,在本例中是C类的范围,并列出它可以找到的所有名为f的函数(无论它们是否可访问,或者是否采用正确的数量参数)。 只有当它不这样做时才继续“向外”进入下一个封闭的范围 [...]
所以是的, f
的const
版本是隐藏的,这是完全正常的。 正如Simone所指出的,您可以使用using
语句将A::f
引入C
范围。
是的。 你可以写:
struct C : public A {
virtual void f() { cout << "C::f" << endl; }
using A::f;
};
使你的代码编译:
int main()
{
const B b;
b.f(); // prints "A::f const"
const C c;
c.f(); // prints "A::f const"
}
有关更多信息,请参阅2010 C ++草案文档(可在此处找到)第10.2章。(3-4)。
隐藏基本成员的不是虚拟性或持久性(或缺乏性),任何派生方法都隐藏同名的基本方法。 这样做是为了改善脆弱的基类问题。
想象一下,您的代码正在运行(可能多年),如下所示,删除了非相关部分:
struct Base {
};
struct Derived : Base {
void f(double);
}
void g(Derived &d) {
d.f(42);
}
然后你需要修改Base以包含一个完全不同的方法,但是,出于某种原因,你想要命名为'f':
struct Base {
void f(int);
};
如果没有这个规则, 每次使用Derived调用f都需要手动评估 - 如果Base是在给其他人的库中,你甚至可能无法访问其他用途! 面对用户定义的(隐式)转换,情况会变得更糟。
相反,决定要求派生类明确声明他们想要使用using声明从Base导入给定的名称。 这个规则可能令人惊讶,我不确定这对今天的语言有什么好处,但是他们没有问我 - 当时,我可能只能用双音节的单词回答它们。 :)
using B::f;
插入using B::f;
struct C : public A {
using A::f;
virtual void f() { cout << "C::f" << endl; }
};
C ++ Standard 2003. 13.2第1页:
如果两个函数声明属于同一作用域且具有等效的参数声明(13.1),则它们引用相同的函数。 派生类的函数成员与基类中的同名函数成员不在同一范围内。
因此C::f
隐藏了所有A::f
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.