[英]How does overload resolution work in the context of private modifier?
我無法理解以下C ++代碼段的輸出。
objc.fn()
不應調用A
的fn()
因為B的fn()
是private
並且在C
不可見。 但是,答案是:對fn()
的調用是模棱兩可的。 怎么樣?
#include<iostream>
using namespace std;
class A{
public:
void fn() { cout << "1"; }
};
class B{
void fn() { cout << "2"; }
};
class C: public A, public B {};
int main(){
C objc;
objc.fn();
return 0;
}
根據《 C ++模板:完整指南》附錄B.1所述,
在很高的層次上,可以通過以下方式處理對命名函數的調用:
查找名稱以形成初始過載集。
如有必要,可以通過各種方式調整此集合(例如,進行模板推導)。
完全不匹配調用的任何候選對象(即使在考慮了隱式轉換和默認參數之后)也將從重載集中刪除。 這產生了一組所謂的可行功能候選。
執行過載解析以找到最佳候選者。 如果有一個,則選擇它; 否則,通話不明確。
檢查所選的候選者。 例如,如果它是不可訪問的私人成員,那么將發出診斷信息。
如您所見,最后檢查了訪問權限,因此將首先在步驟4中報告the call to fn() is ambiguous
。
考慮一下:
class D {
void fn1() {}
public:
void fn2() {}
};
int main() {
D d;
d.fn2(); // Compiles fine
d.fn1(); // Error: fn1 is private
}
請注意, d.fn1()
的錯誤是關於fn1
是私有的,而不是在該范圍內fn1
是未知的或不可見的。 同樣, B::fn
在C
確實可見。
之所以會出現這種情況,是因為編譯器對公共成員和私有成員的名稱解析都相同。 僅在名稱解析后,可訪問性檢查才起作用。
這是你的情況是一樣的:哪個fn
你的意思是? 只有回答了這個問題,編譯器才能告訴您是否可以訪問該fn
。
正如我所懷疑的那樣,此代碼給出了模糊的引用,無法編譯。 由於您已聲明兩個函數具有相同的簽名,因此編譯器不知道要選擇哪個函數,從而在編譯時出現問題。
$ make pru
g++ pru.cc -o pru
pru.cc: In function ‘int main()’:
pru.cc:15:8: error: request for member ‘fn’ is ambiguous
pru.cc:9:9: error: candidates are: void B::fn()
pru.cc:6:9: error: void A::fn()
make: *** [pru] Error 1
我認為您可以選擇要使用的功能,並放置A :: fn()選擇器。 即使在本例中就是其中一個函數是私有的,您也有兩個函數可供選擇(您可以從B方法內部進行調用,並且會得到相同的錯誤---如果您對這兩種方法都具有可見性)。
@songyuanyao已經給出了正確的答案。
最后檢查訪問說明符是由C ++標准委員會設計的 。
如果不是這樣,將會發生以下情況:
讓我們假設訪問說明符阻止函數參與重載解析,然后:
class A{
public:
void fn() { cout << "1"; }
};
class B{
void fn() { cout << "2"; }
};
class C: public A, public B {};
int main(){
C objc;
objc.fn(); // A::fn() is being invoked
return 0;
}
現在我們修改代碼:
class A{
void fn() { cout << "1"; }
};
class B{
public:
void fn() { cout << "2"; }
};
沒有其他感動,突然
objc.fn(); // B::fn() is being invoked
函數的調用者不知道他的基礎函數不再相同。
這是褻瀆!
為了防止所有此類不幸事件發生,標准委員會做出了此設計決定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.