簡體   English   中英

為什么這段代碼會編譯?

[英]Why does this code compile?

確定嵌套在其他對象的私有部分中的對象的訪問權限的確切規則是什么?

例如,在下面的代碼中, proxy_t結構嵌套在abc_t的私有部分中,但它的方法可用於main function。 為什么它會編譯?

#include <iostream>
#include <valarray>

using namespace std;

class abc_t{
  private: 
    struct proxy_t{
      proxy_t operator()(double& a, double& b){ __a=a; __b=b; return *this; }
      double a(){ return __a; }
      double b(){ return __b; }
      private:
        double __a, __b;
    };

  public:
    abc_t( const size_t N ){ 
       _a.resize(N,-101.); 
       _b.resize(N,-202.);  
    }
    double a(size_t j){ return _a[j]; }
    double b(size_t j){ return _b[j]; }

    proxy_t operator[](const size_t j) { return _proxy(_a[j],_b[j]); }

  private:
    valarray<double> _a;
    valarray<double> _b;
    proxy_t _proxy;
};


int main(){
 size_t n_elem=10;
 abc_t abc(n_elem);
 cout<<"direct: "<< abc.a(1)<<"  "<<abc.b(1)<<"\n";
 cout<<"proxied:"<<abc[1].a()<<"  "<<abc[1].b()<<"\n";  // ain't proxy_t::aa() private?
 //cout<<abc[1]; // doomed to fail
}

這條線是我要談論的重要的一條:

cout<<"proxied:"<<abc[1].a()<<"  "<<abc[1].b()<<"\n";

當您調用 abc[1] 時,這是 abc_t 的公共方法。 這是有效的。

它返回一個proxy_t。 盡管未定義此 class (proxy_t) 的聲明,但您實際上並未使用該返回變量來創建新的 object。 如果您要執行以下操作,它將無法編譯。

proxy_t p = abc[1];

它崩潰了,因為正在聲明 proxy_t,您正在初始化一個新的 object,但是該類型在 scope 中不存在。 由於您實際上並未聲明該類型的任何變量,因此在該 scope 中沒有創建任何 proxy_t (這將是非法的)。

通過 proxy_t 是私有的,這僅僅意味着您不能在任何地方創建該類型的任何對象,除了在 abc_t class 內。 但是,它作為返回值傳遞,這是有效的——沒有對象被創建/實例化/聲明,只有一個現有的對象被傳遞。

然后是有趣的部分。 對於類,默認情況下所有內容都是私有的(除非另有說明)。 使用結構,默認情況下所有內容都是 public 因此,proxy_t::a() 是公共的,因此可以在 main 中使用,因為 main 恰好可以訪問 proxy_t object。

您已將結構 proxy_t 定義為私有,但它公開的實際方法是公共的。 我的猜測是您的編譯器不允許您直接在 main 中實例化 proxy_t 結構,但如果您從 class abc_t 返回一個,它將允許您在其上調用公共方法。

也許知道 C++ 標准的人可以評論這是否是編譯器的正確行為。

你說 abc[1].a() 在這里說 go :

proxy_t operator[](const size_t j) { return _proxy(_a[j],_b[j]); }

這是公開的,並且將 1 投入到 j 中。 然后它返回

_proxy(_a[j],_b[j]) 

它正在調用您用來訪問 a() function 的私有結構

由於proxy_t是 abc_t 的私有成員,因此除了abc_t之外abc_t人可以使用它(即實例化這種類型的對象)。 然而,給定一個現有的proxy_t ,每個人都可以調用它的成員——因為它們是公共的。

這里的標准有點沉悶(或者我看錯了地方),但這是我最好的發現(11.8):

嵌套的 class 是一個成員,因此具有與任何其他成員相同的訪問權限。 封閉 class 的成員對嵌套 class 的成員沒有特殊訪問權限; 應遵守通常的訪問規則(第 11 條)。

字里行間閱讀:由於嵌套的 class 只是一個成員,因此當有人引用此類型時(即拼寫proxy_t )應用通常的訪問控制。 但是對於proxy_t本身的成員的訪問,沒有特殊的訪問規則適用 - 如果您設法從特權來源獲得proxy_t object,您可以訪問其成員,就好像它不是嵌套的 class 一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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