Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code compile?

Tags:

c++

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
}
like image 928
ev-br Avatar asked Apr 27 '11 16:04

ev-br


2 Answers

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.

like image 174
Andrew Rasmussen Avatar answered Oct 29 '22 14:10

Andrew Rasmussen


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.

like image 42
Nathanael Avatar answered Oct 29 '22 14:10

Nathanael