简体   繁体   English

覆盖非const虚方法是否会隐藏const重载?

[英]Does overriding a non-const virtual method hide a const overload?

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.) (我正在使用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? 所以f()的const版本似乎隐藏在C语言中。这对我来说很有意义,但它是否受标准规定?

I will (once more) link this great article : 我将(再次)链接这篇伟大的文章

First, [the compiler] looks in the immediate scope, in this case the scope of class C, and makes a list of all functions it can find that are named f (regardless of whether they're accessible or even take the right number of parameters). 首先,[编译器]查看直接范围,在本例中是C类的范围,并列出它可以找到的所有名为f的函数(无论它们是否可访问,或者是否采用正确的数量参数)。 Only if it doesn't does it then continue "outward" into the next enclosing scope [...] 只有当它不这样做时才继续“向外”进入下一个封闭的范围 [...]

So yes, the const version of f is hidden, and that's perfectly normal. 所以是的, fconst版本是隐藏的,这是完全正常的。 As pointed out by Simone, you can use a using statement to bring A::f in C scope. 正如Simone所指出的,您可以使用using语句将A::f引入C范围。

Yes, it is. 是的。 You may write: 你可以写:

struct C : public A {
   virtual void f() { cout << "C::f" << endl; }
   using A::f;       
};

to make your code compile: 使你的代码编译:

int main()
{
   const B b;
   b.f();   // prints "A::f const"

   const C c;
   c.f();   // prints "A::f const"
}

For more infos, you can refer to the 2010 C++ draft document's (which you can find here ) chapter 10.2.(3-4). 有关更多信息,请参阅2010 C ++草案文档(可在此处找到)第10.2章。(3-4)。

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: 想象一下,您的代码正在运行(可能多年),如下所示,删除了非相关部分:

struct Base {
};

struct Derived : Base {
  void f(double);
}

void g(Derived &d) {
  d.f(42);
}

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': 然后你需要修改Base以包含一个完全不同的方法,但是,出于某种原因,你想要命名为'f':

struct Base {
  void f(int);
};

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! 如果没有这个规则, 每次使用Derived调用f都需要手动评估 - 如果Base是在给其他人的库中,你甚至可能无法访问其他用途! 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. 相反,决定要求派生类明确声明他们想要使用using声明从Base导入给定的名称。 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. 这个规则可能令人惊讶,我不确定这对今天的语言有什么好处,但是他们没有问我 - 当时,我可能只能用双音节的单词回答它们。 :) :)

Insert using B::f; 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 p.1: C ++ Standard 2003. 13.2第1页:

Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations (13.1). 如果两个函数声明属于同一作用域且具有等效的参数声明(13.1),则它们引用相同的函数。 A function member of a derived class is not in the same scope as a function member of the same name in a base class. 派生类的函数成员与基类中的同名函数成员不在同一范围内。

Thus C::f hides all A::f . 因此C::f隐藏了所有A::f

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM