[英]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.