簡體   English   中英

重載解析如何在private修飾符的上下文中起作用?

[英]How does overload resolution work in the context of private modifier?

我無法理解以下C ++代碼段的輸出。

objc.fn()不應調用Afn()因為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所述,

在很高的層次上,可以通過以下方式處理對命名函數的調用:

  1. 查找名稱以形成初始過載集。

  2. 如有必要,可以通過各種方式調整此集合(例如,進行模板推導)。

  3. 完全不匹配調用的任何候選對象(即使在考慮了隱式轉換和默認參數之后)也將從重載集中刪除。 這產生了一組所謂的可行功能候選。

  4. 執行過載解析以找到最佳候選者。 如果有一個,則選擇它; 否則,通話不明確。

  5. 檢查所選的候選者。 例如,如果它是不可訪問的私人成員,那么將發出診斷信息。

如您所見,最后檢查了訪問權限,因此將首先在步驟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::fnC確實可見。

之所以會出現這種情況,是因為編譯器對公共成員和私有成員的名稱解析都相同。 僅在名稱解析后,可訪問性檢查才起作用。

這是你的情況是一樣的:哪個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.

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