繁体   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