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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With