簡體   English   中英

覆蓋非const虛方法是否會隱藏const重載?

[英]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的函數(無論它們是否可訪問,或者是否采用正確的數量參數)。 只有當它不這樣做時才繼續“向外”進入下一個封閉的范圍 [...]

所以是的, fconst版本是隱藏的,這是完全正常的。 正如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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM