简体   繁体   中英

Why does this code compile?

What are the exact rules for deciding the access rights for the objects nested into the private sections of other objects?

For example, in the code snipped below, the proxy_t struct is nested into the private section of the abc_t , and yet its methods are available to the main function. Why does it compile at all?

#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
}

This line is the important one that I'm gonna talk about:

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

When you call abc[1], this is a public method of abc_t. This is valid.

It returns a proxy_t. Although the declaration of this class (proxy_t) is not defined, you aren't actually using that return variable to create a new object. If you were to do the following, it wouldn't compile.

proxy_t p = abc[1];

It crashes with that because proxy_t is being declared, you are initializing a new object, however that type doesn't exist in that scope. Since you aren't actually declaring any variables of that type, nothing of proxy_t is being created in that scope (which would be illegal).

By proxy_t being private, that simply means you can't create any objects of that type anywhere except from within the abc_t class. However, it's being passed as a return value, which is valid -- no objects are being created/instantiated/declared, just an existing one is being passed.

Then the fun part. With classes, everything by default is private (unless specified otherwise). With structs, everything by default is public . Therefore, proxy_t::a() is public, and therefore CAN be used in main because main happens to have access to a proxy_t object.

You have defined the struct proxy_t as private, but the actual methods it exposes are public. My guess is that your compiler will not allow you to directly instantiate a proxy_t struct in main, but if you return one from class abc_t, it will allow you to call public methods on it.

Perhaps someone who knows the C++ standard can comment if this is correct behaviour for a compiler or not.

You're saying abc[1].a() which says go here:

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

which is public and throws that 1 in for j. Then it returns

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

which is calling the private struct that you use to access the a() function

Since proxy_t is a private member to abc_t , no one except abc_t can use it (ie instantiate objects of this type). However, given an existing proxy_t , everybody can invoke its members - because they are public.

The standard is a bit dull here (or I'm looking at the wrong place), but this is my best finding (11.8):

A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules (Clause 11) shall be obeyed.

Reading between the lines: Since a nested class is 'just' a member, usual access control is applied when somebody refers to this type (ie spells out proxy_t ). But for access to members of proxy_t itself, no special access rules apply - if you managed to get a proxy_t object from a privileged source, you can access its members as if it wasn't a nested class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM